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


      1// SPDX-License-Identifier: GPL-2.0-only
      2/******************************************************************************
      3 *
      4 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
      5 * Copyright (C) 2018 Intel Corporation
      6 *****************************************************************************/
      7
      8#include <linux/slab.h>
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/debugfs.h>
     12#include <linux/ieee80211.h>
     13#include <net/mac80211.h>
     14
     15#include "iwl-debug.h"
     16#include "iwl-trans.h"
     17#include "iwl-io.h"
     18#include "dev.h"
     19#include "agn.h"
     20
     21/* create and remove of files */
     22#define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
     23	debugfs_create_file(#name, mode, parent, priv,			\
     24			    &iwl_dbgfs_##name##_ops);			\
     25} while (0)
     26
     27/* file operation */
     28#define DEBUGFS_READ_FILE_OPS(name)                                     \
     29static const struct file_operations iwl_dbgfs_##name##_ops = {          \
     30	.read = iwl_dbgfs_##name##_read,				\
     31	.open = simple_open,						\
     32	.llseek = generic_file_llseek,					\
     33};
     34
     35#define DEBUGFS_WRITE_FILE_OPS(name)                                    \
     36static const struct file_operations iwl_dbgfs_##name##_ops = {          \
     37	.write = iwl_dbgfs_##name##_write,                              \
     38	.open = simple_open,						\
     39	.llseek = generic_file_llseek,					\
     40};
     41
     42
     43#define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \
     44static const struct file_operations iwl_dbgfs_##name##_ops = {          \
     45	.write = iwl_dbgfs_##name##_write,                              \
     46	.read = iwl_dbgfs_##name##_read,                                \
     47	.open = simple_open,						\
     48	.llseek = generic_file_llseek,					\
     49};
     50
     51static ssize_t iwl_dbgfs_sram_read(struct file *file,
     52					char __user *user_buf,
     53					size_t count, loff_t *ppos)
     54{
     55	u32 val = 0;
     56	char *buf;
     57	ssize_t ret;
     58	int i = 0;
     59	bool device_format = false;
     60	int offset = 0;
     61	int len = 0;
     62	int pos = 0;
     63	int sram;
     64	struct iwl_priv *priv = file->private_data;
     65	const struct fw_img *img;
     66	size_t bufsz;
     67
     68	if (!iwl_is_ready_rf(priv))
     69		return -EAGAIN;
     70
     71	/* default is to dump the entire data segment */
     72	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
     73		priv->dbgfs_sram_offset = 0x800000;
     74		if (!priv->ucode_loaded)
     75			return -EINVAL;
     76		img = &priv->fw->img[priv->cur_ucode];
     77		priv->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
     78	}
     79	len = priv->dbgfs_sram_len;
     80
     81	if (len == -4) {
     82		device_format = true;
     83		len = 4;
     84	}
     85
     86	bufsz =  50 + len * 4;
     87	buf = kmalloc(bufsz, GFP_KERNEL);
     88	if (!buf)
     89		return -ENOMEM;
     90
     91	pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
     92			 len);
     93	pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
     94			priv->dbgfs_sram_offset);
     95
     96	/* adjust sram address since reads are only on even u32 boundaries */
     97	offset = priv->dbgfs_sram_offset & 0x3;
     98	sram = priv->dbgfs_sram_offset & ~0x3;
     99
    100	/* read the first u32 from sram */
    101	val = iwl_trans_read_mem32(priv->trans, sram);
    102
    103	for (; len; len--) {
    104		/* put the address at the start of every line */
    105		if (i == 0)
    106			pos += scnprintf(buf + pos, bufsz - pos,
    107				"%08X: ", sram + offset);
    108
    109		if (device_format)
    110			pos += scnprintf(buf + pos, bufsz - pos,
    111				"%02x", (val >> (8 * (3 - offset))) & 0xff);
    112		else
    113			pos += scnprintf(buf + pos, bufsz - pos,
    114				"%02x ", (val >> (8 * offset)) & 0xff);
    115
    116		/* if all bytes processed, read the next u32 from sram */
    117		if (++offset == 4) {
    118			sram += 4;
    119			offset = 0;
    120			val = iwl_trans_read_mem32(priv->trans, sram);
    121		}
    122
    123		/* put in extra spaces and split lines for human readability */
    124		if (++i == 16) {
    125			i = 0;
    126			pos += scnprintf(buf + pos, bufsz - pos, "\n");
    127		} else if (!(i & 7)) {
    128			pos += scnprintf(buf + pos, bufsz - pos, "   ");
    129		} else if (!(i & 3)) {
    130			pos += scnprintf(buf + pos, bufsz - pos, " ");
    131		}
    132	}
    133	if (i)
    134		pos += scnprintf(buf + pos, bufsz - pos, "\n");
    135
    136	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    137	kfree(buf);
    138	return ret;
    139}
    140
    141static ssize_t iwl_dbgfs_sram_write(struct file *file,
    142					const char __user *user_buf,
    143					size_t count, loff_t *ppos)
    144{
    145	struct iwl_priv *priv = file->private_data;
    146	char buf[64];
    147	int buf_size;
    148	u32 offset, len;
    149
    150	memset(buf, 0, sizeof(buf));
    151	buf_size = min(count, sizeof(buf) -  1);
    152	if (copy_from_user(buf, user_buf, buf_size))
    153		return -EFAULT;
    154
    155	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
    156		priv->dbgfs_sram_offset = offset;
    157		priv->dbgfs_sram_len = len;
    158	} else if (sscanf(buf, "%x", &offset) == 1) {
    159		priv->dbgfs_sram_offset = offset;
    160		priv->dbgfs_sram_len = -4;
    161	} else {
    162		priv->dbgfs_sram_offset = 0;
    163		priv->dbgfs_sram_len = 0;
    164	}
    165
    166	return count;
    167}
    168
    169static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
    170					  char __user *user_buf,
    171					  size_t count, loff_t *ppos)
    172{
    173	struct iwl_priv *priv = file->private_data;
    174	const struct fw_img *img = &priv->fw->img[IWL_UCODE_WOWLAN];
    175
    176	if (!priv->wowlan_sram)
    177		return -ENODATA;
    178
    179	return simple_read_from_buffer(user_buf, count, ppos,
    180				       priv->wowlan_sram,
    181				       img->sec[IWL_UCODE_SECTION_DATA].len);
    182}
    183static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
    184					size_t count, loff_t *ppos)
    185{
    186	struct iwl_priv *priv = file->private_data;
    187	struct iwl_station_entry *station;
    188	struct iwl_tid_data *tid_data;
    189	char *buf;
    190	int i, j, pos = 0;
    191	ssize_t ret;
    192	/* Add 30 for initial string */
    193	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
    194
    195	buf = kmalloc(bufsz, GFP_KERNEL);
    196	if (!buf)
    197		return -ENOMEM;
    198
    199	pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
    200			priv->num_stations);
    201
    202	for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
    203		station = &priv->stations[i];
    204		if (!station->used)
    205			continue;
    206		pos += scnprintf(buf + pos, bufsz - pos,
    207				 "station %d - addr: %pM, flags: %#x\n",
    208				 i, station->sta.sta.addr,
    209				 station->sta.station_flags_msk);
    210		pos += scnprintf(buf + pos, bufsz - pos,
    211				"TID seqno  next_rclmd "
    212				"rate_n_flags state txq\n");
    213
    214		for (j = 0; j < IWL_MAX_TID_COUNT; j++) {
    215			tid_data = &priv->tid_data[i][j];
    216			pos += scnprintf(buf + pos, bufsz - pos,
    217				"%d:  0x%.4x 0x%.4x     0x%.8x   "
    218				"%d     %.2d",
    219				j, tid_data->seq_number,
    220				tid_data->next_reclaimed,
    221				tid_data->agg.rate_n_flags,
    222				tid_data->agg.state,
    223				tid_data->agg.txq_id);
    224
    225			if (tid_data->agg.wait_for_ba)
    226				pos += scnprintf(buf + pos, bufsz - pos,
    227						 " - waitforba");
    228			pos += scnprintf(buf + pos, bufsz - pos, "\n");
    229		}
    230
    231		pos += scnprintf(buf + pos, bufsz - pos, "\n");
    232	}
    233
    234	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    235	kfree(buf);
    236	return ret;
    237}
    238
    239static ssize_t iwl_dbgfs_nvm_read(struct file *file,
    240				       char __user *user_buf,
    241				       size_t count,
    242				       loff_t *ppos)
    243{
    244	ssize_t ret;
    245	struct iwl_priv *priv = file->private_data;
    246	int pos = 0, ofs = 0, buf_size = 0;
    247	const u8 *ptr;
    248	char *buf;
    249	u16 nvm_ver;
    250	size_t eeprom_len = priv->eeprom_blob_size;
    251	buf_size = 4 * eeprom_len + 256;
    252
    253	if (eeprom_len % 16)
    254		return -ENODATA;
    255
    256	ptr = priv->eeprom_blob;
    257	if (!ptr)
    258		return -ENOMEM;
    259
    260	/* 4 characters for byte 0xYY */
    261	buf = kzalloc(buf_size, GFP_KERNEL);
    262	if (!buf)
    263		return -ENOMEM;
    264
    265	nvm_ver = priv->nvm_data->nvm_version;
    266	pos += scnprintf(buf + pos, buf_size - pos,
    267			 "NVM version: 0x%x\n", nvm_ver);
    268	for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
    269		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",
    270				 ofs, ptr + ofs);
    271	}
    272
    273	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    274	kfree(buf);
    275	return ret;
    276}
    277
    278static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
    279				       size_t count, loff_t *ppos)
    280{
    281	struct iwl_priv *priv = file->private_data;
    282	struct ieee80211_channel *channels = NULL;
    283	const struct ieee80211_supported_band *supp_band = NULL;
    284	int pos = 0, i, bufsz = PAGE_SIZE;
    285	char *buf;
    286	ssize_t ret;
    287
    288	buf = kzalloc(bufsz, GFP_KERNEL);
    289	if (!buf)
    290		return -ENOMEM;
    291
    292	supp_band = iwl_get_hw_mode(priv, NL80211_BAND_2GHZ);
    293	if (supp_band) {
    294		channels = supp_band->channels;
    295
    296		pos += scnprintf(buf + pos, bufsz - pos,
    297				"Displaying %d channels in 2.4GHz band 802.11bg):\n",
    298				supp_band->n_channels);
    299
    300		for (i = 0; i < supp_band->n_channels; i++)
    301			pos += scnprintf(buf + pos, bufsz - pos,
    302					"%d: %ddBm: BSS%s%s, %s.\n",
    303					channels[i].hw_value,
    304					channels[i].max_power,
    305					channels[i].flags & IEEE80211_CHAN_RADAR ?
    306					" (IEEE 802.11h required)" : "",
    307					((channels[i].flags & IEEE80211_CHAN_NO_IR)
    308					|| (channels[i].flags &
    309					IEEE80211_CHAN_RADAR)) ? "" :
    310					", IBSS",
    311					channels[i].flags &
    312					IEEE80211_CHAN_NO_IR ?
    313					"passive only" : "active/passive");
    314	}
    315	supp_band = iwl_get_hw_mode(priv, NL80211_BAND_5GHZ);
    316	if (supp_band) {
    317		channels = supp_band->channels;
    318
    319		pos += scnprintf(buf + pos, bufsz - pos,
    320				"Displaying %d channels in 5.2GHz band (802.11a)\n",
    321				supp_band->n_channels);
    322
    323		for (i = 0; i < supp_band->n_channels; i++)
    324			pos += scnprintf(buf + pos, bufsz - pos,
    325					"%d: %ddBm: BSS%s%s, %s.\n",
    326					channels[i].hw_value,
    327					channels[i].max_power,
    328					channels[i].flags & IEEE80211_CHAN_RADAR ?
    329					" (IEEE 802.11h required)" : "",
    330					((channels[i].flags & IEEE80211_CHAN_NO_IR)
    331					|| (channels[i].flags &
    332					IEEE80211_CHAN_RADAR)) ? "" :
    333					", IBSS",
    334					channels[i].flags &
    335					IEEE80211_CHAN_NO_IR ?
    336					"passive only" : "active/passive");
    337	}
    338	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    339	kfree(buf);
    340	return ret;
    341}
    342
    343static ssize_t iwl_dbgfs_status_read(struct file *file,
    344						char __user *user_buf,
    345						size_t count, loff_t *ppos) {
    346
    347	struct iwl_priv *priv = file->private_data;
    348	char buf[512];
    349	int pos = 0;
    350	const size_t bufsz = sizeof(buf);
    351
    352	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
    353		test_bit(STATUS_RF_KILL_HW, &priv->status));
    354	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
    355		test_bit(STATUS_CT_KILL, &priv->status));
    356	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
    357		test_bit(STATUS_ALIVE, &priv->status));
    358	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
    359		test_bit(STATUS_READY, &priv->status));
    360	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
    361		test_bit(STATUS_EXIT_PENDING, &priv->status));
    362	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
    363		test_bit(STATUS_STATISTICS, &priv->status));
    364	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
    365		test_bit(STATUS_SCANNING, &priv->status));
    366	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
    367		test_bit(STATUS_SCAN_ABORTING, &priv->status));
    368	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
    369		test_bit(STATUS_SCAN_HW, &priv->status));
    370	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
    371		test_bit(STATUS_POWER_PMI, &priv->status));
    372	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
    373		test_bit(STATUS_FW_ERROR, &priv->status));
    374	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    375}
    376
    377static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file,
    378					char __user *user_buf,
    379					size_t count, loff_t *ppos) {
    380
    381	struct iwl_priv *priv = file->private_data;
    382
    383	int pos = 0;
    384	int cnt = 0;
    385	char *buf;
    386	int bufsz = 24 * 64; /* 24 items * 64 char per item */
    387	ssize_t ret;
    388
    389	buf = kzalloc(bufsz, GFP_KERNEL);
    390	if (!buf)
    391		return -ENOMEM;
    392
    393	for (cnt = 0; cnt < REPLY_MAX; cnt++) {
    394		if (priv->rx_handlers_stats[cnt] > 0)
    395			pos += scnprintf(buf + pos, bufsz - pos,
    396				"\tRx handler[%36s]:\t\t %u\n",
    397				iwl_get_cmd_string(priv->trans, (u32)cnt),
    398				priv->rx_handlers_stats[cnt]);
    399	}
    400
    401	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    402	kfree(buf);
    403	return ret;
    404}
    405
    406static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file,
    407					 const char __user *user_buf,
    408					 size_t count, loff_t *ppos)
    409{
    410	struct iwl_priv *priv = file->private_data;
    411
    412	char buf[8];
    413	int buf_size;
    414	u32 reset_flag;
    415
    416	memset(buf, 0, sizeof(buf));
    417	buf_size = min(count, sizeof(buf) -  1);
    418	if (copy_from_user(buf, user_buf, buf_size))
    419		return -EFAULT;
    420	if (sscanf(buf, "%x", &reset_flag) != 1)
    421		return -EFAULT;
    422	if (reset_flag == 0)
    423		memset(&priv->rx_handlers_stats[0], 0,
    424			sizeof(priv->rx_handlers_stats));
    425
    426	return count;
    427}
    428
    429static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
    430				       size_t count, loff_t *ppos)
    431{
    432	struct iwl_priv *priv = file->private_data;
    433	struct iwl_rxon_context *ctx;
    434	int pos = 0, i;
    435	char buf[256 * NUM_IWL_RXON_CTX];
    436	const size_t bufsz = sizeof(buf);
    437
    438	for_each_context(priv, ctx) {
    439		pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
    440				 ctx->ctxid);
    441		for (i = 0; i < AC_NUM; i++) {
    442			pos += scnprintf(buf + pos, bufsz - pos,
    443				"\tcw_min\tcw_max\taifsn\ttxop\n");
    444			pos += scnprintf(buf + pos, bufsz - pos,
    445				"AC[%d]\t%u\t%u\t%u\t%u\n", i,
    446				ctx->qos_data.def_qos_parm.ac[i].cw_min,
    447				ctx->qos_data.def_qos_parm.ac[i].cw_max,
    448				ctx->qos_data.def_qos_parm.ac[i].aifsn,
    449				ctx->qos_data.def_qos_parm.ac[i].edca_txop);
    450		}
    451		pos += scnprintf(buf + pos, bufsz - pos, "\n");
    452	}
    453	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    454}
    455
    456static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
    457				char __user *user_buf,
    458				size_t count, loff_t *ppos)
    459{
    460	struct iwl_priv *priv = file->private_data;
    461	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
    462	struct iwl_tt_restriction *restriction;
    463	char buf[100];
    464	int pos = 0;
    465	const size_t bufsz = sizeof(buf);
    466
    467	pos += scnprintf(buf + pos, bufsz - pos,
    468			"Thermal Throttling Mode: %s\n",
    469			tt->advanced_tt ? "Advance" : "Legacy");
    470	pos += scnprintf(buf + pos, bufsz - pos,
    471			"Thermal Throttling State: %d\n",
    472			tt->state);
    473	if (tt->advanced_tt) {
    474		restriction = tt->restriction + tt->state;
    475		pos += scnprintf(buf + pos, bufsz - pos,
    476				"Tx mode: %d\n",
    477				restriction->tx_stream);
    478		pos += scnprintf(buf + pos, bufsz - pos,
    479				"Rx mode: %d\n",
    480				restriction->rx_stream);
    481		pos += scnprintf(buf + pos, bufsz - pos,
    482				"HT mode: %d\n",
    483				restriction->is_ht);
    484	}
    485	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    486}
    487
    488static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
    489					 const char __user *user_buf,
    490					 size_t count, loff_t *ppos)
    491{
    492	struct iwl_priv *priv = file->private_data;
    493	char buf[8];
    494	int buf_size;
    495	int ht40;
    496
    497	memset(buf, 0, sizeof(buf));
    498	buf_size = min(count, sizeof(buf) -  1);
    499	if (copy_from_user(buf, user_buf, buf_size))
    500		return -EFAULT;
    501	if (sscanf(buf, "%d", &ht40) != 1)
    502		return -EFAULT;
    503	if (!iwl_is_any_associated(priv))
    504		priv->disable_ht40 = ht40 ? true : false;
    505	else
    506		return -EINVAL;
    507
    508	return count;
    509}
    510
    511static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
    512					 char __user *user_buf,
    513					 size_t count, loff_t *ppos)
    514{
    515	struct iwl_priv *priv = file->private_data;
    516	char buf[100];
    517	int pos = 0;
    518	const size_t bufsz = sizeof(buf);
    519
    520	pos += scnprintf(buf + pos, bufsz - pos,
    521			"11n 40MHz Mode: %s\n",
    522			priv->disable_ht40 ? "Disabled" : "Enabled");
    523	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    524}
    525
    526static ssize_t iwl_dbgfs_temperature_read(struct file *file,
    527					 char __user *user_buf,
    528					 size_t count, loff_t *ppos)
    529{
    530	struct iwl_priv *priv = file->private_data;
    531	char buf[8];
    532	int pos = 0;
    533	const size_t bufsz = sizeof(buf);
    534
    535	pos += scnprintf(buf + pos, bufsz - pos, "%d\n", priv->temperature);
    536	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    537}
    538
    539
    540static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
    541						    const char __user *user_buf,
    542						    size_t count, loff_t *ppos)
    543{
    544	struct iwl_priv *priv = file->private_data;
    545	char buf[8];
    546	int buf_size;
    547	int value;
    548
    549	memset(buf, 0, sizeof(buf));
    550	buf_size = min(count, sizeof(buf) -  1);
    551	if (copy_from_user(buf, user_buf, buf_size))
    552		return -EFAULT;
    553
    554	if (sscanf(buf, "%d", &value) != 1)
    555		return -EINVAL;
    556
    557	/*
    558	 * Our users expect 0 to be "CAM", but 0 isn't actually
    559	 * valid here. However, let's not confuse them and present
    560	 * IWL_POWER_INDEX_1 as "1", not "0".
    561	 */
    562	if (value == 0)
    563		return -EINVAL;
    564	else if (value > 0)
    565		value -= 1;
    566
    567	if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
    568		return -EINVAL;
    569
    570	if (!iwl_is_ready_rf(priv))
    571		return -EAGAIN;
    572
    573	priv->power_data.debug_sleep_level_override = value;
    574
    575	mutex_lock(&priv->mutex);
    576	iwl_power_update_mode(priv, true);
    577	mutex_unlock(&priv->mutex);
    578
    579	return count;
    580}
    581
    582static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
    583						   char __user *user_buf,
    584						   size_t count, loff_t *ppos)
    585{
    586	struct iwl_priv *priv = file->private_data;
    587	char buf[10];
    588	int pos, value;
    589	const size_t bufsz = sizeof(buf);
    590
    591	/* see the write function */
    592	value = priv->power_data.debug_sleep_level_override;
    593	if (value >= 0)
    594		value += 1;
    595
    596	pos = scnprintf(buf, bufsz, "%d\n", value);
    597	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    598}
    599
    600static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
    601						    char __user *user_buf,
    602						    size_t count, loff_t *ppos)
    603{
    604	struct iwl_priv *priv = file->private_data;
    605	char buf[200];
    606	int pos = 0, i;
    607	const size_t bufsz = sizeof(buf);
    608	struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
    609
    610	pos += scnprintf(buf + pos, bufsz - pos,
    611			 "flags: %#.2x\n", le16_to_cpu(cmd->flags));
    612	pos += scnprintf(buf + pos, bufsz - pos,
    613			 "RX/TX timeout: %d/%d usec\n",
    614			 le32_to_cpu(cmd->rx_data_timeout),
    615			 le32_to_cpu(cmd->tx_data_timeout));
    616	for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
    617		pos += scnprintf(buf + pos, bufsz - pos,
    618				 "sleep_interval[%d]: %d\n", i,
    619				 le32_to_cpu(cmd->sleep_interval[i]));
    620
    621	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
    622}
    623
    624DEBUGFS_READ_WRITE_FILE_OPS(sram);
    625DEBUGFS_READ_FILE_OPS(wowlan_sram);
    626DEBUGFS_READ_FILE_OPS(nvm);
    627DEBUGFS_READ_FILE_OPS(stations);
    628DEBUGFS_READ_FILE_OPS(channels);
    629DEBUGFS_READ_FILE_OPS(status);
    630DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers);
    631DEBUGFS_READ_FILE_OPS(qos);
    632DEBUGFS_READ_FILE_OPS(thermal_throttling);
    633DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
    634DEBUGFS_READ_FILE_OPS(temperature);
    635DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
    636DEBUGFS_READ_FILE_OPS(current_sleep_command);
    637
    638#define fmt_value	"  %-30s %10u\n"
    639#define fmt_hex		"  %-30s       0x%02X\n"
    640#define fmt_table	"  %-30s %10u  %10u  %10u  %10u\n"
    641#define fmt_header	"%-32s    current  cumulative       delta         max\n"
    642
    643static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
    644{
    645	int p = 0;
    646	u32 flag;
    647
    648	lockdep_assert_held(&priv->statistics.lock);
    649
    650	flag = le32_to_cpu(priv->statistics.flag);
    651
    652	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
    653	if (flag & UCODE_STATISTICS_CLEAR_MSK)
    654		p += scnprintf(buf + p, bufsz - p,
    655		"\tStatistics have been cleared\n");
    656	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
    657		(flag & UCODE_STATISTICS_FREQUENCY_MSK)
    658		? "2.4 GHz" : "5.2 GHz");
    659	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
    660		(flag & UCODE_STATISTICS_NARROW_BAND_MSK)
    661		 ? "enabled" : "disabled");
    662
    663	return p;
    664}
    665
    666static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
    667					char __user *user_buf,
    668					size_t count, loff_t *ppos)
    669{
    670	struct iwl_priv *priv = file->private_data;
    671	int pos = 0;
    672	char *buf;
    673	int bufsz = sizeof(struct statistics_rx_phy) * 40 +
    674		    sizeof(struct statistics_rx_non_phy) * 40 +
    675		    sizeof(struct statistics_rx_ht_phy) * 40 + 400;
    676	ssize_t ret;
    677	struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
    678	struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
    679	struct statistics_rx_non_phy *general, *accum_general;
    680	struct statistics_rx_non_phy *delta_general, *max_general;
    681	struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
    682
    683	if (!iwl_is_alive(priv))
    684		return -EAGAIN;
    685
    686	buf = kzalloc(bufsz, GFP_KERNEL);
    687	if (!buf)
    688		return -ENOMEM;
    689
    690	/*
    691	 * the statistic information display here is based on
    692	 * the last statistics notification from uCode
    693	 * might not reflect the current uCode activity
    694	 */
    695	spin_lock_bh(&priv->statistics.lock);
    696	ofdm = &priv->statistics.rx_ofdm;
    697	cck = &priv->statistics.rx_cck;
    698	general = &priv->statistics.rx_non_phy;
    699	ht = &priv->statistics.rx_ofdm_ht;
    700	accum_ofdm = &priv->accum_stats.rx_ofdm;
    701	accum_cck = &priv->accum_stats.rx_cck;
    702	accum_general = &priv->accum_stats.rx_non_phy;
    703	accum_ht = &priv->accum_stats.rx_ofdm_ht;
    704	delta_ofdm = &priv->delta_stats.rx_ofdm;
    705	delta_cck = &priv->delta_stats.rx_cck;
    706	delta_general = &priv->delta_stats.rx_non_phy;
    707	delta_ht = &priv->delta_stats.rx_ofdm_ht;
    708	max_ofdm = &priv->max_delta_stats.rx_ofdm;
    709	max_cck = &priv->max_delta_stats.rx_cck;
    710	max_general = &priv->max_delta_stats.rx_non_phy;
    711	max_ht = &priv->max_delta_stats.rx_ofdm_ht;
    712
    713	pos += iwl_statistics_flag(priv, buf, bufsz);
    714	pos += scnprintf(buf + pos, bufsz - pos,
    715			 fmt_header, "Statistics_Rx - OFDM:");
    716	pos += scnprintf(buf + pos, bufsz - pos,
    717			 fmt_table, "ina_cnt:",
    718			 le32_to_cpu(ofdm->ina_cnt),
    719			 accum_ofdm->ina_cnt,
    720			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
    721	pos += scnprintf(buf + pos, bufsz - pos,
    722			 fmt_table, "fina_cnt:",
    723			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
    724			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
    725	pos += scnprintf(buf + pos, bufsz - pos,
    726			 fmt_table, "plcp_err:",
    727			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
    728			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
    729	pos += scnprintf(buf + pos, bufsz - pos,
    730			 fmt_table, "crc32_err:",
    731			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
    732			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
    733	pos += scnprintf(buf + pos, bufsz - pos,
    734			 fmt_table, "overrun_err:",
    735			 le32_to_cpu(ofdm->overrun_err),
    736			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
    737			 max_ofdm->overrun_err);
    738	pos += scnprintf(buf + pos, bufsz - pos,
    739			 fmt_table, "early_overrun_err:",
    740			 le32_to_cpu(ofdm->early_overrun_err),
    741			 accum_ofdm->early_overrun_err,
    742			 delta_ofdm->early_overrun_err,
    743			 max_ofdm->early_overrun_err);
    744	pos += scnprintf(buf + pos, bufsz - pos,
    745			 fmt_table, "crc32_good:",
    746			 le32_to_cpu(ofdm->crc32_good),
    747			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
    748			 max_ofdm->crc32_good);
    749	pos += scnprintf(buf + pos, bufsz - pos,
    750			 fmt_table, "false_alarm_cnt:",
    751			 le32_to_cpu(ofdm->false_alarm_cnt),
    752			 accum_ofdm->false_alarm_cnt,
    753			 delta_ofdm->false_alarm_cnt,
    754			 max_ofdm->false_alarm_cnt);
    755	pos += scnprintf(buf + pos, bufsz - pos,
    756			 fmt_table, "fina_sync_err_cnt:",
    757			 le32_to_cpu(ofdm->fina_sync_err_cnt),
    758			 accum_ofdm->fina_sync_err_cnt,
    759			 delta_ofdm->fina_sync_err_cnt,
    760			 max_ofdm->fina_sync_err_cnt);
    761	pos += scnprintf(buf + pos, bufsz - pos,
    762			 fmt_table, "sfd_timeout:",
    763			 le32_to_cpu(ofdm->sfd_timeout),
    764			 accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,
    765			 max_ofdm->sfd_timeout);
    766	pos += scnprintf(buf + pos, bufsz - pos,
    767			 fmt_table, "fina_timeout:",
    768			 le32_to_cpu(ofdm->fina_timeout),
    769			 accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,
    770			 max_ofdm->fina_timeout);
    771	pos += scnprintf(buf + pos, bufsz - pos,
    772			 fmt_table, "unresponded_rts:",
    773			 le32_to_cpu(ofdm->unresponded_rts),
    774			 accum_ofdm->unresponded_rts,
    775			 delta_ofdm->unresponded_rts,
    776			 max_ofdm->unresponded_rts);
    777	pos += scnprintf(buf + pos, bufsz - pos,
    778			 fmt_table, "rxe_frame_lmt_ovrun:",
    779			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
    780			 accum_ofdm->rxe_frame_limit_overrun,
    781			 delta_ofdm->rxe_frame_limit_overrun,
    782			 max_ofdm->rxe_frame_limit_overrun);
    783	pos += scnprintf(buf + pos, bufsz - pos,
    784			 fmt_table, "sent_ack_cnt:",
    785			 le32_to_cpu(ofdm->sent_ack_cnt),
    786			 accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,
    787			 max_ofdm->sent_ack_cnt);
    788	pos += scnprintf(buf + pos, bufsz - pos,
    789			 fmt_table, "sent_cts_cnt:",
    790			 le32_to_cpu(ofdm->sent_cts_cnt),
    791			 accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,
    792			 max_ofdm->sent_cts_cnt);
    793	pos += scnprintf(buf + pos, bufsz - pos,
    794			 fmt_table, "sent_ba_rsp_cnt:",
    795			 le32_to_cpu(ofdm->sent_ba_rsp_cnt),
    796			 accum_ofdm->sent_ba_rsp_cnt,
    797			 delta_ofdm->sent_ba_rsp_cnt,
    798			 max_ofdm->sent_ba_rsp_cnt);
    799	pos += scnprintf(buf + pos, bufsz - pos,
    800			 fmt_table, "dsp_self_kill:",
    801			 le32_to_cpu(ofdm->dsp_self_kill),
    802			 accum_ofdm->dsp_self_kill,
    803			 delta_ofdm->dsp_self_kill,
    804			 max_ofdm->dsp_self_kill);
    805	pos += scnprintf(buf + pos, bufsz - pos,
    806			 fmt_table, "mh_format_err:",
    807			 le32_to_cpu(ofdm->mh_format_err),
    808			 accum_ofdm->mh_format_err,
    809			 delta_ofdm->mh_format_err,
    810			 max_ofdm->mh_format_err);
    811	pos += scnprintf(buf + pos, bufsz - pos,
    812			 fmt_table, "re_acq_main_rssi_sum:",
    813			 le32_to_cpu(ofdm->re_acq_main_rssi_sum),
    814			 accum_ofdm->re_acq_main_rssi_sum,
    815			 delta_ofdm->re_acq_main_rssi_sum,
    816			 max_ofdm->re_acq_main_rssi_sum);
    817
    818	pos += scnprintf(buf + pos, bufsz - pos,
    819			 fmt_header, "Statistics_Rx - CCK:");
    820	pos += scnprintf(buf + pos, bufsz - pos,
    821			 fmt_table, "ina_cnt:",
    822			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
    823			 delta_cck->ina_cnt, max_cck->ina_cnt);
    824	pos += scnprintf(buf + pos, bufsz - pos,
    825			 fmt_table, "fina_cnt:",
    826			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
    827			 delta_cck->fina_cnt, max_cck->fina_cnt);
    828	pos += scnprintf(buf + pos, bufsz - pos,
    829			 fmt_table, "plcp_err:",
    830			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
    831			 delta_cck->plcp_err, max_cck->plcp_err);
    832	pos += scnprintf(buf + pos, bufsz - pos,
    833			 fmt_table, "crc32_err:",
    834			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
    835			 delta_cck->crc32_err, max_cck->crc32_err);
    836	pos += scnprintf(buf + pos, bufsz - pos,
    837			 fmt_table, "overrun_err:",
    838			 le32_to_cpu(cck->overrun_err),
    839			 accum_cck->overrun_err, delta_cck->overrun_err,
    840			 max_cck->overrun_err);
    841	pos += scnprintf(buf + pos, bufsz - pos,
    842			 fmt_table, "early_overrun_err:",
    843			 le32_to_cpu(cck->early_overrun_err),
    844			 accum_cck->early_overrun_err,
    845			 delta_cck->early_overrun_err,
    846			 max_cck->early_overrun_err);
    847	pos += scnprintf(buf + pos, bufsz - pos,
    848			 fmt_table, "crc32_good:",
    849			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
    850			 delta_cck->crc32_good, max_cck->crc32_good);
    851	pos += scnprintf(buf + pos, bufsz - pos,
    852			 fmt_table, "false_alarm_cnt:",
    853			 le32_to_cpu(cck->false_alarm_cnt),
    854			 accum_cck->false_alarm_cnt,
    855			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
    856	pos += scnprintf(buf + pos, bufsz - pos,
    857			 fmt_table, "fina_sync_err_cnt:",
    858			 le32_to_cpu(cck->fina_sync_err_cnt),
    859			 accum_cck->fina_sync_err_cnt,
    860			 delta_cck->fina_sync_err_cnt,
    861			 max_cck->fina_sync_err_cnt);
    862	pos += scnprintf(buf + pos, bufsz - pos,
    863			 fmt_table, "sfd_timeout:",
    864			 le32_to_cpu(cck->sfd_timeout),
    865			 accum_cck->sfd_timeout, delta_cck->sfd_timeout,
    866			 max_cck->sfd_timeout);
    867	pos += scnprintf(buf + pos, bufsz - pos,
    868			 fmt_table, "fina_timeout:",
    869			 le32_to_cpu(cck->fina_timeout),
    870			 accum_cck->fina_timeout, delta_cck->fina_timeout,
    871			 max_cck->fina_timeout);
    872	pos += scnprintf(buf + pos, bufsz - pos,
    873			 fmt_table, "unresponded_rts:",
    874			 le32_to_cpu(cck->unresponded_rts),
    875			 accum_cck->unresponded_rts, delta_cck->unresponded_rts,
    876			 max_cck->unresponded_rts);
    877	pos += scnprintf(buf + pos, bufsz - pos,
    878			 fmt_table, "rxe_frame_lmt_ovrun:",
    879			 le32_to_cpu(cck->rxe_frame_limit_overrun),
    880			 accum_cck->rxe_frame_limit_overrun,
    881			 delta_cck->rxe_frame_limit_overrun,
    882			 max_cck->rxe_frame_limit_overrun);
    883	pos += scnprintf(buf + pos, bufsz - pos,
    884			 fmt_table, "sent_ack_cnt:",
    885			 le32_to_cpu(cck->sent_ack_cnt),
    886			 accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,
    887			 max_cck->sent_ack_cnt);
    888	pos += scnprintf(buf + pos, bufsz - pos,
    889			 fmt_table, "sent_cts_cnt:",
    890			 le32_to_cpu(cck->sent_cts_cnt),
    891			 accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,
    892			 max_cck->sent_cts_cnt);
    893	pos += scnprintf(buf + pos, bufsz - pos,
    894			 fmt_table, "sent_ba_rsp_cnt:",
    895			 le32_to_cpu(cck->sent_ba_rsp_cnt),
    896			 accum_cck->sent_ba_rsp_cnt,
    897			 delta_cck->sent_ba_rsp_cnt,
    898			 max_cck->sent_ba_rsp_cnt);
    899	pos += scnprintf(buf + pos, bufsz - pos,
    900			 fmt_table, "dsp_self_kill:",
    901			 le32_to_cpu(cck->dsp_self_kill),
    902			 accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,
    903			 max_cck->dsp_self_kill);
    904	pos += scnprintf(buf + pos, bufsz - pos,
    905			 fmt_table, "mh_format_err:",
    906			 le32_to_cpu(cck->mh_format_err),
    907			 accum_cck->mh_format_err, delta_cck->mh_format_err,
    908			 max_cck->mh_format_err);
    909	pos += scnprintf(buf + pos, bufsz - pos,
    910			 fmt_table, "re_acq_main_rssi_sum:",
    911			 le32_to_cpu(cck->re_acq_main_rssi_sum),
    912			 accum_cck->re_acq_main_rssi_sum,
    913			 delta_cck->re_acq_main_rssi_sum,
    914			 max_cck->re_acq_main_rssi_sum);
    915
    916	pos += scnprintf(buf + pos, bufsz - pos,
    917			 fmt_header, "Statistics_Rx - GENERAL:");
    918	pos += scnprintf(buf + pos, bufsz - pos,
    919			 fmt_table, "bogus_cts:",
    920			 le32_to_cpu(general->bogus_cts),
    921			 accum_general->bogus_cts, delta_general->bogus_cts,
    922			 max_general->bogus_cts);
    923	pos += scnprintf(buf + pos, bufsz - pos,
    924			 fmt_table, "bogus_ack:",
    925			 le32_to_cpu(general->bogus_ack),
    926			 accum_general->bogus_ack, delta_general->bogus_ack,
    927			 max_general->bogus_ack);
    928	pos += scnprintf(buf + pos, bufsz - pos,
    929			 fmt_table, "non_bssid_frames:",
    930			 le32_to_cpu(general->non_bssid_frames),
    931			 accum_general->non_bssid_frames,
    932			 delta_general->non_bssid_frames,
    933			 max_general->non_bssid_frames);
    934	pos += scnprintf(buf + pos, bufsz - pos,
    935			 fmt_table, "filtered_frames:",
    936			 le32_to_cpu(general->filtered_frames),
    937			 accum_general->filtered_frames,
    938			 delta_general->filtered_frames,
    939			 max_general->filtered_frames);
    940	pos += scnprintf(buf + pos, bufsz - pos,
    941			 fmt_table, "non_channel_beacons:",
    942			 le32_to_cpu(general->non_channel_beacons),
    943			 accum_general->non_channel_beacons,
    944			 delta_general->non_channel_beacons,
    945			 max_general->non_channel_beacons);
    946	pos += scnprintf(buf + pos, bufsz - pos,
    947			 fmt_table, "channel_beacons:",
    948			 le32_to_cpu(general->channel_beacons),
    949			 accum_general->channel_beacons,
    950			 delta_general->channel_beacons,
    951			 max_general->channel_beacons);
    952	pos += scnprintf(buf + pos, bufsz - pos,
    953			 fmt_table, "num_missed_bcon:",
    954			 le32_to_cpu(general->num_missed_bcon),
    955			 accum_general->num_missed_bcon,
    956			 delta_general->num_missed_bcon,
    957			 max_general->num_missed_bcon);
    958	pos += scnprintf(buf + pos, bufsz - pos,
    959			 fmt_table, "adc_rx_saturation_time:",
    960			 le32_to_cpu(general->adc_rx_saturation_time),
    961			 accum_general->adc_rx_saturation_time,
    962			 delta_general->adc_rx_saturation_time,
    963			 max_general->adc_rx_saturation_time);
    964	pos += scnprintf(buf + pos, bufsz - pos,
    965			 fmt_table, "ina_detect_search_tm:",
    966			 le32_to_cpu(general->ina_detection_search_time),
    967			 accum_general->ina_detection_search_time,
    968			 delta_general->ina_detection_search_time,
    969			 max_general->ina_detection_search_time);
    970	pos += scnprintf(buf + pos, bufsz - pos,
    971			 fmt_table, "beacon_silence_rssi_a:",
    972			 le32_to_cpu(general->beacon_silence_rssi_a),
    973			 accum_general->beacon_silence_rssi_a,
    974			 delta_general->beacon_silence_rssi_a,
    975			 max_general->beacon_silence_rssi_a);
    976	pos += scnprintf(buf + pos, bufsz - pos,
    977			 fmt_table, "beacon_silence_rssi_b:",
    978			 le32_to_cpu(general->beacon_silence_rssi_b),
    979			 accum_general->beacon_silence_rssi_b,
    980			 delta_general->beacon_silence_rssi_b,
    981			 max_general->beacon_silence_rssi_b);
    982	pos += scnprintf(buf + pos, bufsz - pos,
    983			 fmt_table, "beacon_silence_rssi_c:",
    984			 le32_to_cpu(general->beacon_silence_rssi_c),
    985			 accum_general->beacon_silence_rssi_c,
    986			 delta_general->beacon_silence_rssi_c,
    987			 max_general->beacon_silence_rssi_c);
    988	pos += scnprintf(buf + pos, bufsz - pos,
    989			 fmt_table, "interference_data_flag:",
    990			 le32_to_cpu(general->interference_data_flag),
    991			 accum_general->interference_data_flag,
    992			 delta_general->interference_data_flag,
    993			 max_general->interference_data_flag);
    994	pos += scnprintf(buf + pos, bufsz - pos,
    995			 fmt_table, "channel_load:",
    996			 le32_to_cpu(general->channel_load),
    997			 accum_general->channel_load,
    998			 delta_general->channel_load,
    999			 max_general->channel_load);
   1000	pos += scnprintf(buf + pos, bufsz - pos,
   1001			 fmt_table, "dsp_false_alarms:",
   1002			 le32_to_cpu(general->dsp_false_alarms),
   1003			 accum_general->dsp_false_alarms,
   1004			 delta_general->dsp_false_alarms,
   1005			 max_general->dsp_false_alarms);
   1006	pos += scnprintf(buf + pos, bufsz - pos,
   1007			 fmt_table, "beacon_rssi_a:",
   1008			 le32_to_cpu(general->beacon_rssi_a),
   1009			 accum_general->beacon_rssi_a,
   1010			 delta_general->beacon_rssi_a,
   1011			 max_general->beacon_rssi_a);
   1012	pos += scnprintf(buf + pos, bufsz - pos,
   1013			 fmt_table, "beacon_rssi_b:",
   1014			 le32_to_cpu(general->beacon_rssi_b),
   1015			 accum_general->beacon_rssi_b,
   1016			 delta_general->beacon_rssi_b,
   1017			 max_general->beacon_rssi_b);
   1018	pos += scnprintf(buf + pos, bufsz - pos,
   1019			 fmt_table, "beacon_rssi_c:",
   1020			 le32_to_cpu(general->beacon_rssi_c),
   1021			 accum_general->beacon_rssi_c,
   1022			 delta_general->beacon_rssi_c,
   1023			 max_general->beacon_rssi_c);
   1024	pos += scnprintf(buf + pos, bufsz - pos,
   1025			 fmt_table, "beacon_energy_a:",
   1026			 le32_to_cpu(general->beacon_energy_a),
   1027			 accum_general->beacon_energy_a,
   1028			 delta_general->beacon_energy_a,
   1029			 max_general->beacon_energy_a);
   1030	pos += scnprintf(buf + pos, bufsz - pos,
   1031			 fmt_table, "beacon_energy_b:",
   1032			 le32_to_cpu(general->beacon_energy_b),
   1033			 accum_general->beacon_energy_b,
   1034			 delta_general->beacon_energy_b,
   1035			 max_general->beacon_energy_b);
   1036	pos += scnprintf(buf + pos, bufsz - pos,
   1037			 fmt_table, "beacon_energy_c:",
   1038			 le32_to_cpu(general->beacon_energy_c),
   1039			 accum_general->beacon_energy_c,
   1040			 delta_general->beacon_energy_c,
   1041			 max_general->beacon_energy_c);
   1042
   1043	pos += scnprintf(buf + pos, bufsz - pos,
   1044			 fmt_header, "Statistics_Rx - OFDM_HT:");
   1045	pos += scnprintf(buf + pos, bufsz - pos,
   1046			 fmt_table, "plcp_err:",
   1047			 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
   1048			 delta_ht->plcp_err, max_ht->plcp_err);
   1049	pos += scnprintf(buf + pos, bufsz - pos,
   1050			 fmt_table, "overrun_err:",
   1051			 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
   1052			 delta_ht->overrun_err, max_ht->overrun_err);
   1053	pos += scnprintf(buf + pos, bufsz - pos,
   1054			 fmt_table, "early_overrun_err:",
   1055			 le32_to_cpu(ht->early_overrun_err),
   1056			 accum_ht->early_overrun_err,
   1057			 delta_ht->early_overrun_err,
   1058			 max_ht->early_overrun_err);
   1059	pos += scnprintf(buf + pos, bufsz - pos,
   1060			 fmt_table, "crc32_good:",
   1061			 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
   1062			 delta_ht->crc32_good, max_ht->crc32_good);
   1063	pos += scnprintf(buf + pos, bufsz - pos,
   1064			 fmt_table, "crc32_err:",
   1065			 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
   1066			 delta_ht->crc32_err, max_ht->crc32_err);
   1067	pos += scnprintf(buf + pos, bufsz - pos,
   1068			 fmt_table, "mh_format_err:",
   1069			 le32_to_cpu(ht->mh_format_err),
   1070			 accum_ht->mh_format_err,
   1071			 delta_ht->mh_format_err, max_ht->mh_format_err);
   1072	pos += scnprintf(buf + pos, bufsz - pos,
   1073			 fmt_table, "agg_crc32_good:",
   1074			 le32_to_cpu(ht->agg_crc32_good),
   1075			 accum_ht->agg_crc32_good,
   1076			 delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
   1077	pos += scnprintf(buf + pos, bufsz - pos,
   1078			 fmt_table, "agg_mpdu_cnt:",
   1079			 le32_to_cpu(ht->agg_mpdu_cnt),
   1080			 accum_ht->agg_mpdu_cnt,
   1081			 delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
   1082	pos += scnprintf(buf + pos, bufsz - pos,
   1083			 fmt_table, "agg_cnt:",
   1084			 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
   1085			 delta_ht->agg_cnt, max_ht->agg_cnt);
   1086	pos += scnprintf(buf + pos, bufsz - pos,
   1087			 fmt_table, "unsupport_mcs:",
   1088			 le32_to_cpu(ht->unsupport_mcs),
   1089			 accum_ht->unsupport_mcs,
   1090			 delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
   1091
   1092	spin_unlock_bh(&priv->statistics.lock);
   1093
   1094	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1095	kfree(buf);
   1096	return ret;
   1097}
   1098
   1099static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
   1100					char __user *user_buf,
   1101					size_t count, loff_t *ppos)
   1102{
   1103	struct iwl_priv *priv = file->private_data;
   1104	int pos = 0;
   1105	char *buf;
   1106	int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
   1107	ssize_t ret;
   1108	struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
   1109
   1110	if (!iwl_is_alive(priv))
   1111		return -EAGAIN;
   1112
   1113	buf = kzalloc(bufsz, GFP_KERNEL);
   1114	if (!buf)
   1115		return -ENOMEM;
   1116
   1117	/* the statistic information display here is based on
   1118	 * the last statistics notification from uCode
   1119	 * might not reflect the current uCode activity
   1120	 */
   1121	spin_lock_bh(&priv->statistics.lock);
   1122
   1123	tx = &priv->statistics.tx;
   1124	accum_tx = &priv->accum_stats.tx;
   1125	delta_tx = &priv->delta_stats.tx;
   1126	max_tx = &priv->max_delta_stats.tx;
   1127
   1128	pos += iwl_statistics_flag(priv, buf, bufsz);
   1129	pos += scnprintf(buf + pos, bufsz - pos,
   1130			 fmt_header, "Statistics_Tx:");
   1131	pos += scnprintf(buf + pos, bufsz - pos,
   1132			 fmt_table, "preamble:",
   1133			 le32_to_cpu(tx->preamble_cnt),
   1134			 accum_tx->preamble_cnt,
   1135			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
   1136	pos += scnprintf(buf + pos, bufsz - pos,
   1137			 fmt_table, "rx_detected_cnt:",
   1138			 le32_to_cpu(tx->rx_detected_cnt),
   1139			 accum_tx->rx_detected_cnt,
   1140			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
   1141	pos += scnprintf(buf + pos, bufsz - pos,
   1142			 fmt_table, "bt_prio_defer_cnt:",
   1143			 le32_to_cpu(tx->bt_prio_defer_cnt),
   1144			 accum_tx->bt_prio_defer_cnt,
   1145			 delta_tx->bt_prio_defer_cnt,
   1146			 max_tx->bt_prio_defer_cnt);
   1147	pos += scnprintf(buf + pos, bufsz - pos,
   1148			 fmt_table, "bt_prio_kill_cnt:",
   1149			 le32_to_cpu(tx->bt_prio_kill_cnt),
   1150			 accum_tx->bt_prio_kill_cnt,
   1151			 delta_tx->bt_prio_kill_cnt,
   1152			 max_tx->bt_prio_kill_cnt);
   1153	pos += scnprintf(buf + pos, bufsz - pos,
   1154			 fmt_table, "few_bytes_cnt:",
   1155			 le32_to_cpu(tx->few_bytes_cnt),
   1156			 accum_tx->few_bytes_cnt,
   1157			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
   1158	pos += scnprintf(buf + pos, bufsz - pos,
   1159			 fmt_table, "cts_timeout:",
   1160			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
   1161			 delta_tx->cts_timeout, max_tx->cts_timeout);
   1162	pos += scnprintf(buf + pos, bufsz - pos,
   1163			 fmt_table, "ack_timeout:",
   1164			 le32_to_cpu(tx->ack_timeout),
   1165			 accum_tx->ack_timeout,
   1166			 delta_tx->ack_timeout, max_tx->ack_timeout);
   1167	pos += scnprintf(buf + pos, bufsz - pos,
   1168			 fmt_table, "expected_ack_cnt:",
   1169			 le32_to_cpu(tx->expected_ack_cnt),
   1170			 accum_tx->expected_ack_cnt,
   1171			 delta_tx->expected_ack_cnt,
   1172			 max_tx->expected_ack_cnt);
   1173	pos += scnprintf(buf + pos, bufsz - pos,
   1174			 fmt_table, "actual_ack_cnt:",
   1175			 le32_to_cpu(tx->actual_ack_cnt),
   1176			 accum_tx->actual_ack_cnt,
   1177			 delta_tx->actual_ack_cnt,
   1178			 max_tx->actual_ack_cnt);
   1179	pos += scnprintf(buf + pos, bufsz - pos,
   1180			 fmt_table, "dump_msdu_cnt:",
   1181			 le32_to_cpu(tx->dump_msdu_cnt),
   1182			 accum_tx->dump_msdu_cnt,
   1183			 delta_tx->dump_msdu_cnt,
   1184			 max_tx->dump_msdu_cnt);
   1185	pos += scnprintf(buf + pos, bufsz - pos,
   1186			 fmt_table, "abort_nxt_frame_mismatch:",
   1187			 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
   1188			 accum_tx->burst_abort_next_frame_mismatch_cnt,
   1189			 delta_tx->burst_abort_next_frame_mismatch_cnt,
   1190			 max_tx->burst_abort_next_frame_mismatch_cnt);
   1191	pos += scnprintf(buf + pos, bufsz - pos,
   1192			 fmt_table, "abort_missing_nxt_frame:",
   1193			 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
   1194			 accum_tx->burst_abort_missing_next_frame_cnt,
   1195			 delta_tx->burst_abort_missing_next_frame_cnt,
   1196			 max_tx->burst_abort_missing_next_frame_cnt);
   1197	pos += scnprintf(buf + pos, bufsz - pos,
   1198			 fmt_table, "cts_timeout_collision:",
   1199			 le32_to_cpu(tx->cts_timeout_collision),
   1200			 accum_tx->cts_timeout_collision,
   1201			 delta_tx->cts_timeout_collision,
   1202			 max_tx->cts_timeout_collision);
   1203	pos += scnprintf(buf + pos, bufsz - pos,
   1204			 fmt_table, "ack_ba_timeout_collision:",
   1205			 le32_to_cpu(tx->ack_or_ba_timeout_collision),
   1206			 accum_tx->ack_or_ba_timeout_collision,
   1207			 delta_tx->ack_or_ba_timeout_collision,
   1208			 max_tx->ack_or_ba_timeout_collision);
   1209	pos += scnprintf(buf + pos, bufsz - pos,
   1210			 fmt_table, "agg ba_timeout:",
   1211			 le32_to_cpu(tx->agg.ba_timeout),
   1212			 accum_tx->agg.ba_timeout,
   1213			 delta_tx->agg.ba_timeout,
   1214			 max_tx->agg.ba_timeout);
   1215	pos += scnprintf(buf + pos, bufsz - pos,
   1216			 fmt_table, "agg ba_resched_frames:",
   1217			 le32_to_cpu(tx->agg.ba_reschedule_frames),
   1218			 accum_tx->agg.ba_reschedule_frames,
   1219			 delta_tx->agg.ba_reschedule_frames,
   1220			 max_tx->agg.ba_reschedule_frames);
   1221	pos += scnprintf(buf + pos, bufsz - pos,
   1222			 fmt_table, "agg scd_query_agg_frame:",
   1223			 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
   1224			 accum_tx->agg.scd_query_agg_frame_cnt,
   1225			 delta_tx->agg.scd_query_agg_frame_cnt,
   1226			 max_tx->agg.scd_query_agg_frame_cnt);
   1227	pos += scnprintf(buf + pos, bufsz - pos,
   1228			 fmt_table, "agg scd_query_no_agg:",
   1229			 le32_to_cpu(tx->agg.scd_query_no_agg),
   1230			 accum_tx->agg.scd_query_no_agg,
   1231			 delta_tx->agg.scd_query_no_agg,
   1232			 max_tx->agg.scd_query_no_agg);
   1233	pos += scnprintf(buf + pos, bufsz - pos,
   1234			 fmt_table, "agg scd_query_agg:",
   1235			 le32_to_cpu(tx->agg.scd_query_agg),
   1236			 accum_tx->agg.scd_query_agg,
   1237			 delta_tx->agg.scd_query_agg,
   1238			 max_tx->agg.scd_query_agg);
   1239	pos += scnprintf(buf + pos, bufsz - pos,
   1240			 fmt_table, "agg scd_query_mismatch:",
   1241			 le32_to_cpu(tx->agg.scd_query_mismatch),
   1242			 accum_tx->agg.scd_query_mismatch,
   1243			 delta_tx->agg.scd_query_mismatch,
   1244			 max_tx->agg.scd_query_mismatch);
   1245	pos += scnprintf(buf + pos, bufsz - pos,
   1246			 fmt_table, "agg frame_not_ready:",
   1247			 le32_to_cpu(tx->agg.frame_not_ready),
   1248			 accum_tx->agg.frame_not_ready,
   1249			 delta_tx->agg.frame_not_ready,
   1250			 max_tx->agg.frame_not_ready);
   1251	pos += scnprintf(buf + pos, bufsz - pos,
   1252			 fmt_table, "agg underrun:",
   1253			 le32_to_cpu(tx->agg.underrun),
   1254			 accum_tx->agg.underrun,
   1255			 delta_tx->agg.underrun, max_tx->agg.underrun);
   1256	pos += scnprintf(buf + pos, bufsz - pos,
   1257			 fmt_table, "agg bt_prio_kill:",
   1258			 le32_to_cpu(tx->agg.bt_prio_kill),
   1259			 accum_tx->agg.bt_prio_kill,
   1260			 delta_tx->agg.bt_prio_kill,
   1261			 max_tx->agg.bt_prio_kill);
   1262	pos += scnprintf(buf + pos, bufsz - pos,
   1263			 fmt_table, "agg rx_ba_rsp_cnt:",
   1264			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
   1265			 accum_tx->agg.rx_ba_rsp_cnt,
   1266			 delta_tx->agg.rx_ba_rsp_cnt,
   1267			 max_tx->agg.rx_ba_rsp_cnt);
   1268
   1269	if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
   1270		pos += scnprintf(buf + pos, bufsz - pos,
   1271			"tx power: (1/2 dB step)\n");
   1272		if ((priv->nvm_data->valid_tx_ant & ANT_A) &&
   1273		    tx->tx_power.ant_a)
   1274			pos += scnprintf(buf + pos, bufsz - pos,
   1275					fmt_hex, "antenna A:",
   1276					tx->tx_power.ant_a);
   1277		if ((priv->nvm_data->valid_tx_ant & ANT_B) &&
   1278		    tx->tx_power.ant_b)
   1279			pos += scnprintf(buf + pos, bufsz - pos,
   1280					fmt_hex, "antenna B:",
   1281					tx->tx_power.ant_b);
   1282		if ((priv->nvm_data->valid_tx_ant & ANT_C) &&
   1283		    tx->tx_power.ant_c)
   1284			pos += scnprintf(buf + pos, bufsz - pos,
   1285					fmt_hex, "antenna C:",
   1286					tx->tx_power.ant_c);
   1287	}
   1288
   1289	spin_unlock_bh(&priv->statistics.lock);
   1290
   1291	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1292	kfree(buf);
   1293	return ret;
   1294}
   1295
   1296static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
   1297					char __user *user_buf,
   1298					size_t count, loff_t *ppos)
   1299{
   1300	struct iwl_priv *priv = file->private_data;
   1301	int pos = 0;
   1302	char *buf;
   1303	int bufsz = sizeof(struct statistics_general) * 10 + 300;
   1304	ssize_t ret;
   1305	struct statistics_general_common *general, *accum_general;
   1306	struct statistics_general_common *delta_general, *max_general;
   1307	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
   1308	struct statistics_div *div, *accum_div, *delta_div, *max_div;
   1309
   1310	if (!iwl_is_alive(priv))
   1311		return -EAGAIN;
   1312
   1313	buf = kzalloc(bufsz, GFP_KERNEL);
   1314	if (!buf)
   1315		return -ENOMEM;
   1316
   1317	/* the statistic information display here is based on
   1318	 * the last statistics notification from uCode
   1319	 * might not reflect the current uCode activity
   1320	 */
   1321
   1322	spin_lock_bh(&priv->statistics.lock);
   1323
   1324	general = &priv->statistics.common;
   1325	dbg = &priv->statistics.common.dbg;
   1326	div = &priv->statistics.common.div;
   1327	accum_general = &priv->accum_stats.common;
   1328	accum_dbg = &priv->accum_stats.common.dbg;
   1329	accum_div = &priv->accum_stats.common.div;
   1330	delta_general = &priv->delta_stats.common;
   1331	max_general = &priv->max_delta_stats.common;
   1332	delta_dbg = &priv->delta_stats.common.dbg;
   1333	max_dbg = &priv->max_delta_stats.common.dbg;
   1334	delta_div = &priv->delta_stats.common.div;
   1335	max_div = &priv->max_delta_stats.common.div;
   1336
   1337	pos += iwl_statistics_flag(priv, buf, bufsz);
   1338	pos += scnprintf(buf + pos, bufsz - pos,
   1339			 fmt_header, "Statistics_General:");
   1340	pos += scnprintf(buf + pos, bufsz - pos,
   1341			 fmt_value, "temperature:",
   1342			 le32_to_cpu(general->temperature));
   1343	pos += scnprintf(buf + pos, bufsz - pos,
   1344			 fmt_value, "temperature_m:",
   1345			 le32_to_cpu(general->temperature_m));
   1346	pos += scnprintf(buf + pos, bufsz - pos,
   1347			 fmt_value, "ttl_timestamp:",
   1348			 le32_to_cpu(general->ttl_timestamp));
   1349	pos += scnprintf(buf + pos, bufsz - pos,
   1350			 fmt_table, "burst_check:",
   1351			 le32_to_cpu(dbg->burst_check),
   1352			 accum_dbg->burst_check,
   1353			 delta_dbg->burst_check, max_dbg->burst_check);
   1354	pos += scnprintf(buf + pos, bufsz - pos,
   1355			 fmt_table, "burst_count:",
   1356			 le32_to_cpu(dbg->burst_count),
   1357			 accum_dbg->burst_count,
   1358			 delta_dbg->burst_count, max_dbg->burst_count);
   1359	pos += scnprintf(buf + pos, bufsz - pos,
   1360			 fmt_table, "wait_for_silence_timeout_count:",
   1361			 le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
   1362			 accum_dbg->wait_for_silence_timeout_cnt,
   1363			 delta_dbg->wait_for_silence_timeout_cnt,
   1364			 max_dbg->wait_for_silence_timeout_cnt);
   1365	pos += scnprintf(buf + pos, bufsz - pos,
   1366			 fmt_table, "sleep_time:",
   1367			 le32_to_cpu(general->sleep_time),
   1368			 accum_general->sleep_time,
   1369			 delta_general->sleep_time, max_general->sleep_time);
   1370	pos += scnprintf(buf + pos, bufsz - pos,
   1371			 fmt_table, "slots_out:",
   1372			 le32_to_cpu(general->slots_out),
   1373			 accum_general->slots_out,
   1374			 delta_general->slots_out, max_general->slots_out);
   1375	pos += scnprintf(buf + pos, bufsz - pos,
   1376			 fmt_table, "slots_idle:",
   1377			 le32_to_cpu(general->slots_idle),
   1378			 accum_general->slots_idle,
   1379			 delta_general->slots_idle, max_general->slots_idle);
   1380	pos += scnprintf(buf + pos, bufsz - pos,
   1381			 fmt_table, "tx_on_a:",
   1382			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
   1383			 delta_div->tx_on_a, max_div->tx_on_a);
   1384	pos += scnprintf(buf + pos, bufsz - pos,
   1385			 fmt_table, "tx_on_b:",
   1386			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
   1387			 delta_div->tx_on_b, max_div->tx_on_b);
   1388	pos += scnprintf(buf + pos, bufsz - pos,
   1389			 fmt_table, "exec_time:",
   1390			 le32_to_cpu(div->exec_time), accum_div->exec_time,
   1391			 delta_div->exec_time, max_div->exec_time);
   1392	pos += scnprintf(buf + pos, bufsz - pos,
   1393			 fmt_table, "probe_time:",
   1394			 le32_to_cpu(div->probe_time), accum_div->probe_time,
   1395			 delta_div->probe_time, max_div->probe_time);
   1396	pos += scnprintf(buf + pos, bufsz - pos,
   1397			 fmt_table, "rx_enable_counter:",
   1398			 le32_to_cpu(general->rx_enable_counter),
   1399			 accum_general->rx_enable_counter,
   1400			 delta_general->rx_enable_counter,
   1401			 max_general->rx_enable_counter);
   1402	pos += scnprintf(buf + pos, bufsz - pos,
   1403			 fmt_table, "num_of_sos_states:",
   1404			 le32_to_cpu(general->num_of_sos_states),
   1405			 accum_general->num_of_sos_states,
   1406			 delta_general->num_of_sos_states,
   1407			 max_general->num_of_sos_states);
   1408
   1409	spin_unlock_bh(&priv->statistics.lock);
   1410
   1411	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1412	kfree(buf);
   1413	return ret;
   1414}
   1415
   1416static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
   1417					char __user *user_buf,
   1418					size_t count, loff_t *ppos)
   1419{
   1420	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
   1421	int pos = 0;
   1422	char *buf;
   1423	int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200;
   1424	ssize_t ret;
   1425	struct statistics_bt_activity *bt, *accum_bt;
   1426
   1427	if (!iwl_is_alive(priv))
   1428		return -EAGAIN;
   1429
   1430	if (!priv->bt_enable_flag)
   1431		return -EINVAL;
   1432
   1433	/* make request to uCode to retrieve statistics information */
   1434	mutex_lock(&priv->mutex);
   1435	ret = iwl_send_statistics_request(priv, 0, false);
   1436	mutex_unlock(&priv->mutex);
   1437
   1438	if (ret)
   1439		return -EAGAIN;
   1440	buf = kzalloc(bufsz, GFP_KERNEL);
   1441	if (!buf)
   1442		return -ENOMEM;
   1443
   1444	/*
   1445	 * the statistic information display here is based on
   1446	 * the last statistics notification from uCode
   1447	 * might not reflect the current uCode activity
   1448	 */
   1449
   1450	spin_lock_bh(&priv->statistics.lock);
   1451
   1452	bt = &priv->statistics.bt_activity;
   1453	accum_bt = &priv->accum_stats.bt_activity;
   1454
   1455	pos += iwl_statistics_flag(priv, buf, bufsz);
   1456	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n");
   1457	pos += scnprintf(buf + pos, bufsz - pos,
   1458			"\t\t\tcurrent\t\t\taccumulative\n");
   1459	pos += scnprintf(buf + pos, bufsz - pos,
   1460			 "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",
   1461			 le32_to_cpu(bt->hi_priority_tx_req_cnt),
   1462			 accum_bt->hi_priority_tx_req_cnt);
   1463	pos += scnprintf(buf + pos, bufsz - pos,
   1464			 "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n",
   1465			 le32_to_cpu(bt->hi_priority_tx_denied_cnt),
   1466			 accum_bt->hi_priority_tx_denied_cnt);
   1467	pos += scnprintf(buf + pos, bufsz - pos,
   1468			 "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",
   1469			 le32_to_cpu(bt->lo_priority_tx_req_cnt),
   1470			 accum_bt->lo_priority_tx_req_cnt);
   1471	pos += scnprintf(buf + pos, bufsz - pos,
   1472			 "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n",
   1473			 le32_to_cpu(bt->lo_priority_tx_denied_cnt),
   1474			 accum_bt->lo_priority_tx_denied_cnt);
   1475	pos += scnprintf(buf + pos, bufsz - pos,
   1476			 "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",
   1477			 le32_to_cpu(bt->hi_priority_rx_req_cnt),
   1478			 accum_bt->hi_priority_rx_req_cnt);
   1479	pos += scnprintf(buf + pos, bufsz - pos,
   1480			 "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
   1481			 le32_to_cpu(bt->hi_priority_rx_denied_cnt),
   1482			 accum_bt->hi_priority_rx_denied_cnt);
   1483	pos += scnprintf(buf + pos, bufsz - pos,
   1484			 "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",
   1485			 le32_to_cpu(bt->lo_priority_rx_req_cnt),
   1486			 accum_bt->lo_priority_rx_req_cnt);
   1487	pos += scnprintf(buf + pos, bufsz - pos,
   1488			 "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
   1489			 le32_to_cpu(bt->lo_priority_rx_denied_cnt),
   1490			 accum_bt->lo_priority_rx_denied_cnt);
   1491
   1492	pos += scnprintf(buf + pos, bufsz - pos,
   1493			 "(rx)num_bt_kills:\t\t%u\t\t\t%u\n",
   1494			 le32_to_cpu(priv->statistics.num_bt_kills),
   1495			 priv->statistics.accum_num_bt_kills);
   1496
   1497	spin_unlock_bh(&priv->statistics.lock);
   1498
   1499	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1500	kfree(buf);
   1501	return ret;
   1502}
   1503
   1504static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
   1505					char __user *user_buf,
   1506					size_t count, loff_t *ppos)
   1507{
   1508	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
   1509	int pos = 0;
   1510	char *buf;
   1511	int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) +
   1512		(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
   1513	ssize_t ret;
   1514
   1515	if (!iwl_is_alive(priv))
   1516		return -EAGAIN;
   1517
   1518	buf = kzalloc(bufsz, GFP_KERNEL);
   1519	if (!buf)
   1520		return -ENOMEM;
   1521
   1522	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n");
   1523	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",
   1524			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),
   1525			 priv->reply_tx_stats.pp_delay);
   1526	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1527			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),
   1528			 priv->reply_tx_stats.pp_few_bytes);
   1529	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1530			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),
   1531			 priv->reply_tx_stats.pp_bt_prio);
   1532	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1533			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),
   1534			 priv->reply_tx_stats.pp_quiet_period);
   1535	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1536			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),
   1537			 priv->reply_tx_stats.pp_calc_ttak);
   1538	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
   1539			 iwl_get_tx_fail_reason(
   1540				TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),
   1541			 priv->reply_tx_stats.int_crossed_retry);
   1542	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1543			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),
   1544			 priv->reply_tx_stats.short_limit);
   1545	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1546			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),
   1547			 priv->reply_tx_stats.long_limit);
   1548	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1549			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),
   1550			 priv->reply_tx_stats.fifo_underrun);
   1551	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1552			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),
   1553			 priv->reply_tx_stats.drain_flow);
   1554	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1555			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),
   1556			 priv->reply_tx_stats.rfkill_flush);
   1557	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1558			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),
   1559			 priv->reply_tx_stats.life_expire);
   1560	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1561			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),
   1562			 priv->reply_tx_stats.dest_ps);
   1563	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1564			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),
   1565			 priv->reply_tx_stats.host_abort);
   1566	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1567			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),
   1568			 priv->reply_tx_stats.pp_delay);
   1569	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1570			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),
   1571			 priv->reply_tx_stats.sta_invalid);
   1572	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1573			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),
   1574			 priv->reply_tx_stats.frag_drop);
   1575	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1576			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),
   1577			 priv->reply_tx_stats.tid_disable);
   1578	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1579			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),
   1580			 priv->reply_tx_stats.fifo_flush);
   1581	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
   1582			 iwl_get_tx_fail_reason(
   1583				TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),
   1584			 priv->reply_tx_stats.insuff_cf_poll);
   1585	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1586			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX),
   1587			 priv->reply_tx_stats.fail_hw_drop);
   1588	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
   1589			 iwl_get_tx_fail_reason(
   1590				TX_STATUS_FAIL_NO_BEACON_ON_RADAR),
   1591			 priv->reply_tx_stats.sta_color_mismatch);
   1592	pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
   1593			 priv->reply_tx_stats.unknown);
   1594
   1595	pos += scnprintf(buf + pos, bufsz - pos,
   1596			 "\nStatistics_Agg_TX_Error:\n");
   1597
   1598	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1599			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK),
   1600			 priv->reply_agg_tx_stats.underrun);
   1601	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1602			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK),
   1603			 priv->reply_agg_tx_stats.bt_prio);
   1604	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1605			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK),
   1606			 priv->reply_agg_tx_stats.few_bytes);
   1607	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1608			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK),
   1609			 priv->reply_agg_tx_stats.abort);
   1610	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
   1611			 iwl_get_agg_tx_fail_reason(
   1612				AGG_TX_STATE_LAST_SENT_TTL_MSK),
   1613			 priv->reply_agg_tx_stats.last_sent_ttl);
   1614	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
   1615			 iwl_get_agg_tx_fail_reason(
   1616				AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK),
   1617			 priv->reply_agg_tx_stats.last_sent_try);
   1618	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
   1619			 iwl_get_agg_tx_fail_reason(
   1620				AGG_TX_STATE_LAST_SENT_BT_KILL_MSK),
   1621			 priv->reply_agg_tx_stats.last_sent_bt_kill);
   1622	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1623			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK),
   1624			 priv->reply_agg_tx_stats.scd_query);
   1625	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
   1626			 iwl_get_agg_tx_fail_reason(
   1627				AGG_TX_STATE_TEST_BAD_CRC32_MSK),
   1628			 priv->reply_agg_tx_stats.bad_crc32);
   1629	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1630			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK),
   1631			 priv->reply_agg_tx_stats.response);
   1632	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1633			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK),
   1634			 priv->reply_agg_tx_stats.dump_tx);
   1635	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
   1636			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK),
   1637			 priv->reply_agg_tx_stats.delay_tx);
   1638	pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
   1639			 priv->reply_agg_tx_stats.unknown);
   1640
   1641	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1642	kfree(buf);
   1643	return ret;
   1644}
   1645
   1646static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
   1647					char __user *user_buf,
   1648					size_t count, loff_t *ppos) {
   1649
   1650	struct iwl_priv *priv = file->private_data;
   1651	int pos = 0;
   1652	int cnt = 0;
   1653	char *buf;
   1654	int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
   1655	ssize_t ret;
   1656	struct iwl_sensitivity_data *data;
   1657
   1658	data = &priv->sensitivity_data;
   1659	buf = kzalloc(bufsz, GFP_KERNEL);
   1660	if (!buf)
   1661		return -ENOMEM;
   1662
   1663	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
   1664			data->auto_corr_ofdm);
   1665	pos += scnprintf(buf + pos, bufsz - pos,
   1666			"auto_corr_ofdm_mrc:\t\t %u\n",
   1667			data->auto_corr_ofdm_mrc);
   1668	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
   1669			data->auto_corr_ofdm_x1);
   1670	pos += scnprintf(buf + pos, bufsz - pos,
   1671			"auto_corr_ofdm_mrc_x1:\t\t %u\n",
   1672			data->auto_corr_ofdm_mrc_x1);
   1673	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
   1674			data->auto_corr_cck);
   1675	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
   1676			data->auto_corr_cck_mrc);
   1677	pos += scnprintf(buf + pos, bufsz - pos,
   1678			"last_bad_plcp_cnt_ofdm:\t\t %u\n",
   1679			data->last_bad_plcp_cnt_ofdm);
   1680	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
   1681			data->last_fa_cnt_ofdm);
   1682	pos += scnprintf(buf + pos, bufsz - pos,
   1683			"last_bad_plcp_cnt_cck:\t\t %u\n",
   1684			data->last_bad_plcp_cnt_cck);
   1685	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
   1686			data->last_fa_cnt_cck);
   1687	pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
   1688			data->nrg_curr_state);
   1689	pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
   1690			data->nrg_prev_state);
   1691	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
   1692	for (cnt = 0; cnt < 10; cnt++) {
   1693		pos += scnprintf(buf + pos, bufsz - pos, " %u",
   1694				data->nrg_value[cnt]);
   1695	}
   1696	pos += scnprintf(buf + pos, bufsz - pos, "\n");
   1697	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
   1698	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
   1699		pos += scnprintf(buf + pos, bufsz - pos, " %u",
   1700				data->nrg_silence_rssi[cnt]);
   1701	}
   1702	pos += scnprintf(buf + pos, bufsz - pos, "\n");
   1703	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
   1704			data->nrg_silence_ref);
   1705	pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
   1706			data->nrg_energy_idx);
   1707	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
   1708			data->nrg_silence_idx);
   1709	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
   1710			data->nrg_th_cck);
   1711	pos += scnprintf(buf + pos, bufsz - pos,
   1712			"nrg_auto_corr_silence_diff:\t %u\n",
   1713			data->nrg_auto_corr_silence_diff);
   1714	pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
   1715			data->num_in_cck_no_fa);
   1716	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
   1717			data->nrg_th_ofdm);
   1718
   1719	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1720	kfree(buf);
   1721	return ret;
   1722}
   1723
   1724
   1725static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
   1726					char __user *user_buf,
   1727					size_t count, loff_t *ppos) {
   1728
   1729	struct iwl_priv *priv = file->private_data;
   1730	int pos = 0;
   1731	int cnt = 0;
   1732	char *buf;
   1733	int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
   1734	ssize_t ret;
   1735	struct iwl_chain_noise_data *data;
   1736
   1737	data = &priv->chain_noise_data;
   1738	buf = kzalloc(bufsz, GFP_KERNEL);
   1739	if (!buf)
   1740		return -ENOMEM;
   1741
   1742	pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
   1743			data->active_chains);
   1744	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
   1745			data->chain_noise_a);
   1746	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
   1747			data->chain_noise_b);
   1748	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
   1749			data->chain_noise_c);
   1750	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
   1751			data->chain_signal_a);
   1752	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
   1753			data->chain_signal_b);
   1754	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
   1755			data->chain_signal_c);
   1756	pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
   1757			data->beacon_count);
   1758
   1759	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
   1760	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
   1761		pos += scnprintf(buf + pos, bufsz - pos, " %u",
   1762				data->disconn_array[cnt]);
   1763	}
   1764	pos += scnprintf(buf + pos, bufsz - pos, "\n");
   1765	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
   1766	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
   1767		pos += scnprintf(buf + pos, bufsz - pos, " %u",
   1768				data->delta_gain_code[cnt]);
   1769	}
   1770	pos += scnprintf(buf + pos, bufsz - pos, "\n");
   1771	pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
   1772			data->radio_write);
   1773	pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
   1774			data->state);
   1775
   1776	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1777	kfree(buf);
   1778	return ret;
   1779}
   1780
   1781static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
   1782						    char __user *user_buf,
   1783						    size_t count, loff_t *ppos)
   1784{
   1785	struct iwl_priv *priv = file->private_data;
   1786	char buf[60];
   1787	int pos = 0;
   1788	const size_t bufsz = sizeof(buf);
   1789	u32 pwrsave_status;
   1790
   1791	pwrsave_status = iwl_read32(priv->trans, CSR_GP_CNTRL) &
   1792			CSR_GP_REG_POWER_SAVE_STATUS_MSK;
   1793
   1794	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
   1795	pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
   1796		(pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
   1797		(pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
   1798		(pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
   1799		"error");
   1800
   1801	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1802}
   1803
   1804static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
   1805					 const char __user *user_buf,
   1806					 size_t count, loff_t *ppos)
   1807{
   1808	struct iwl_priv *priv = file->private_data;
   1809	char buf[8];
   1810	int buf_size;
   1811	int clear;
   1812
   1813	memset(buf, 0, sizeof(buf));
   1814	buf_size = min(count, sizeof(buf) -  1);
   1815	if (copy_from_user(buf, user_buf, buf_size))
   1816		return -EFAULT;
   1817	if (sscanf(buf, "%d", &clear) != 1)
   1818		return -EFAULT;
   1819
   1820	/* make request to uCode to retrieve statistics information */
   1821	mutex_lock(&priv->mutex);
   1822	iwl_send_statistics_request(priv, 0, true);
   1823	mutex_unlock(&priv->mutex);
   1824
   1825	return count;
   1826}
   1827
   1828static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
   1829					char __user *user_buf,
   1830					size_t count, loff_t *ppos) {
   1831
   1832	struct iwl_priv *priv = file->private_data;
   1833	int pos = 0;
   1834	char buf[128];
   1835	const size_t bufsz = sizeof(buf);
   1836
   1837	pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
   1838			priv->event_log.ucode_trace ? "On" : "Off");
   1839	pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
   1840			priv->event_log.non_wraps_count);
   1841	pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
   1842			priv->event_log.wraps_once_count);
   1843	pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
   1844			priv->event_log.wraps_more_count);
   1845
   1846	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1847}
   1848
   1849static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
   1850					 const char __user *user_buf,
   1851					 size_t count, loff_t *ppos)
   1852{
   1853	struct iwl_priv *priv = file->private_data;
   1854	char buf[8];
   1855	int buf_size;
   1856	int trace;
   1857
   1858	memset(buf, 0, sizeof(buf));
   1859	buf_size = min(count, sizeof(buf) -  1);
   1860	if (copy_from_user(buf, user_buf, buf_size))
   1861		return -EFAULT;
   1862	if (sscanf(buf, "%d", &trace) != 1)
   1863		return -EFAULT;
   1864
   1865	if (trace) {
   1866		priv->event_log.ucode_trace = true;
   1867		if (iwl_is_alive(priv)) {
   1868			/* start collecting data now */
   1869			mod_timer(&priv->ucode_trace, jiffies);
   1870		}
   1871	} else {
   1872		priv->event_log.ucode_trace = false;
   1873		del_timer_sync(&priv->ucode_trace);
   1874	}
   1875
   1876	return count;
   1877}
   1878
   1879static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
   1880					 char __user *user_buf,
   1881					 size_t count, loff_t *ppos) {
   1882
   1883	struct iwl_priv *priv = file->private_data;
   1884	int len = 0;
   1885	char buf[20];
   1886
   1887	len = sprintf(buf, "0x%04X\n",
   1888		le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
   1889	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
   1890}
   1891
   1892static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
   1893						char __user *user_buf,
   1894						size_t count, loff_t *ppos) {
   1895
   1896	struct iwl_priv *priv = file->private_data;
   1897	int len = 0;
   1898	char buf[20];
   1899
   1900	len = sprintf(buf, "0x%04X\n",
   1901		le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
   1902	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
   1903}
   1904
   1905static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
   1906					char __user *user_buf,
   1907					size_t count, loff_t *ppos) {
   1908
   1909	struct iwl_priv *priv = file->private_data;
   1910	int pos = 0;
   1911	char buf[12];
   1912	const size_t bufsz = sizeof(buf);
   1913
   1914	pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
   1915			priv->missed_beacon_threshold);
   1916
   1917	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1918}
   1919
   1920static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
   1921					 const char __user *user_buf,
   1922					 size_t count, loff_t *ppos)
   1923{
   1924	struct iwl_priv *priv = file->private_data;
   1925	char buf[8];
   1926	int buf_size;
   1927	int missed;
   1928
   1929	memset(buf, 0, sizeof(buf));
   1930	buf_size = min(count, sizeof(buf) -  1);
   1931	if (copy_from_user(buf, user_buf, buf_size))
   1932		return -EFAULT;
   1933	if (sscanf(buf, "%d", &missed) != 1)
   1934		return -EINVAL;
   1935
   1936	if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
   1937	    missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
   1938		priv->missed_beacon_threshold =
   1939			IWL_MISSED_BEACON_THRESHOLD_DEF;
   1940	else
   1941		priv->missed_beacon_threshold = missed;
   1942
   1943	return count;
   1944}
   1945
   1946static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
   1947					char __user *user_buf,
   1948					size_t count, loff_t *ppos) {
   1949
   1950	struct iwl_priv *priv = file->private_data;
   1951	int pos = 0;
   1952	char buf[12];
   1953	const size_t bufsz = sizeof(buf);
   1954
   1955	pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
   1956			priv->plcp_delta_threshold);
   1957
   1958	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   1959}
   1960
   1961static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
   1962					const char __user *user_buf,
   1963					size_t count, loff_t *ppos) {
   1964
   1965	struct iwl_priv *priv = file->private_data;
   1966	char buf[8];
   1967	int buf_size;
   1968	int plcp;
   1969
   1970	memset(buf, 0, sizeof(buf));
   1971	buf_size = min(count, sizeof(buf) -  1);
   1972	if (copy_from_user(buf, user_buf, buf_size))
   1973		return -EFAULT;
   1974	if (sscanf(buf, "%d", &plcp) != 1)
   1975		return -EINVAL;
   1976	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
   1977		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
   1978		priv->plcp_delta_threshold =
   1979			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
   1980	else
   1981		priv->plcp_delta_threshold = plcp;
   1982	return count;
   1983}
   1984
   1985static ssize_t iwl_dbgfs_rf_reset_read(struct file *file,
   1986				       char __user *user_buf,
   1987				       size_t count, loff_t *ppos)
   1988{
   1989	struct iwl_priv *priv = file->private_data;
   1990	int pos = 0;
   1991	char buf[300];
   1992	const size_t bufsz = sizeof(buf);
   1993	struct iwl_rf_reset *rf_reset = &priv->rf_reset;
   1994
   1995	pos += scnprintf(buf + pos, bufsz - pos,
   1996			"RF reset statistics\n");
   1997	pos += scnprintf(buf + pos, bufsz - pos,
   1998			"\tnumber of reset request: %d\n",
   1999			rf_reset->reset_request_count);
   2000	pos += scnprintf(buf + pos, bufsz - pos,
   2001			"\tnumber of reset request success: %d\n",
   2002			rf_reset->reset_success_count);
   2003	pos += scnprintf(buf + pos, bufsz - pos,
   2004			"\tnumber of reset request reject: %d\n",
   2005			rf_reset->reset_reject_count);
   2006
   2007	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   2008}
   2009
   2010static ssize_t iwl_dbgfs_rf_reset_write(struct file *file,
   2011					const char __user *user_buf,
   2012					size_t count, loff_t *ppos) {
   2013
   2014	struct iwl_priv *priv = file->private_data;
   2015	int ret;
   2016
   2017	ret = iwl_force_rf_reset(priv, true);
   2018	return ret ? ret : count;
   2019}
   2020
   2021static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
   2022					const char __user *user_buf,
   2023					size_t count, loff_t *ppos) {
   2024
   2025	struct iwl_priv *priv = file->private_data;
   2026	char buf[8];
   2027	int buf_size;
   2028	int flush;
   2029
   2030	memset(buf, 0, sizeof(buf));
   2031	buf_size = min(count, sizeof(buf) -  1);
   2032	if (copy_from_user(buf, user_buf, buf_size))
   2033		return -EFAULT;
   2034	if (sscanf(buf, "%d", &flush) != 1)
   2035		return -EINVAL;
   2036
   2037	if (iwl_is_rfkill(priv))
   2038		return -EFAULT;
   2039
   2040	iwlagn_dev_txfifo_flush(priv);
   2041
   2042	return count;
   2043}
   2044
   2045static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file,
   2046					char __user *user_buf,
   2047					size_t count, loff_t *ppos) {
   2048
   2049	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
   2050	int pos = 0;
   2051	char buf[200];
   2052	const size_t bufsz = sizeof(buf);
   2053
   2054	if (!priv->bt_enable_flag) {
   2055		pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n");
   2056		return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   2057	}
   2058	pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n",
   2059		priv->bt_enable_flag);
   2060	pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n",
   2061		priv->bt_full_concurrent ? "full concurrency" : "3-wire");
   2062	pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, "
   2063			 "last traffic notif: %d\n",
   2064		priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load);
   2065	pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, "
   2066			 "kill_ack_mask: %x, kill_cts_mask: %x\n",
   2067		priv->bt_ch_announce, priv->kill_ack_mask,
   2068		priv->kill_cts_mask);
   2069
   2070	pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: ");
   2071	switch (priv->bt_traffic_load) {
   2072	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
   2073		pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n");
   2074		break;
   2075	case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
   2076		pos += scnprintf(buf + pos, bufsz - pos, "High\n");
   2077		break;
   2078	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
   2079		pos += scnprintf(buf + pos, bufsz - pos, "Low\n");
   2080		break;
   2081	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
   2082	default:
   2083		pos += scnprintf(buf + pos, bufsz - pos, "None\n");
   2084		break;
   2085	}
   2086
   2087	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   2088}
   2089
   2090static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
   2091					char __user *user_buf,
   2092					size_t count, loff_t *ppos)
   2093{
   2094	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
   2095
   2096	int pos = 0;
   2097	char buf[40];
   2098	const size_t bufsz = sizeof(buf);
   2099
   2100	if (priv->cfg->ht_params)
   2101		pos += scnprintf(buf + pos, bufsz - pos,
   2102			 "use %s for aggregation\n",
   2103			 (priv->hw_params.use_rts_for_aggregation) ?
   2104				"rts/cts" : "cts-to-self");
   2105	else
   2106		pos += scnprintf(buf + pos, bufsz - pos, "N/A");
   2107
   2108	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   2109}
   2110
   2111static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
   2112					const char __user *user_buf,
   2113					size_t count, loff_t *ppos) {
   2114
   2115	struct iwl_priv *priv = file->private_data;
   2116	char buf[8];
   2117	int buf_size;
   2118	int rts;
   2119
   2120	if (!priv->cfg->ht_params)
   2121		return -EINVAL;
   2122
   2123	memset(buf, 0, sizeof(buf));
   2124	buf_size = min(count, sizeof(buf) -  1);
   2125	if (copy_from_user(buf, user_buf, buf_size))
   2126		return -EFAULT;
   2127	if (sscanf(buf, "%d", &rts) != 1)
   2128		return -EINVAL;
   2129	if (rts)
   2130		priv->hw_params.use_rts_for_aggregation = true;
   2131	else
   2132		priv->hw_params.use_rts_for_aggregation = false;
   2133	return count;
   2134}
   2135
   2136static int iwl_cmd_echo_test(struct iwl_priv *priv)
   2137{
   2138	int ret;
   2139	struct iwl_host_cmd cmd = {
   2140		.id = REPLY_ECHO,
   2141		.len = { 0 },
   2142	};
   2143
   2144	ret = iwl_dvm_send_cmd(priv, &cmd);
   2145	if (ret)
   2146		IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
   2147	else
   2148		IWL_DEBUG_INFO(priv, "echo testing pass\n");
   2149	return ret;
   2150}
   2151
   2152static ssize_t iwl_dbgfs_echo_test_write(struct file *file,
   2153					const char __user *user_buf,
   2154					size_t count, loff_t *ppos)
   2155{
   2156	struct iwl_priv *priv = file->private_data;
   2157	char buf[8];
   2158	int buf_size;
   2159
   2160	memset(buf, 0, sizeof(buf));
   2161	buf_size = min(count, sizeof(buf) -  1);
   2162	if (copy_from_user(buf, user_buf, buf_size))
   2163		return -EFAULT;
   2164
   2165	iwl_cmd_echo_test(priv);
   2166	return count;
   2167}
   2168
   2169#ifdef CONFIG_IWLWIFI_DEBUG
   2170static ssize_t iwl_dbgfs_log_event_read(struct file *file,
   2171					 char __user *user_buf,
   2172					 size_t count, loff_t *ppos)
   2173{
   2174	struct iwl_priv *priv = file->private_data;
   2175	char *buf = NULL;
   2176	ssize_t ret;
   2177
   2178	ret = iwl_dump_nic_event_log(priv, true, &buf);
   2179	if (ret > 0)
   2180		ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
   2181	kfree(buf);
   2182	return ret;
   2183}
   2184
   2185static ssize_t iwl_dbgfs_log_event_write(struct file *file,
   2186					const char __user *user_buf,
   2187					size_t count, loff_t *ppos)
   2188{
   2189	struct iwl_priv *priv = file->private_data;
   2190	u32 event_log_flag;
   2191	char buf[8];
   2192	int buf_size;
   2193
   2194	/* check that the interface is up */
   2195	if (!iwl_is_ready(priv))
   2196		return -EAGAIN;
   2197
   2198	memset(buf, 0, sizeof(buf));
   2199	buf_size = min(count, sizeof(buf) -  1);
   2200	if (copy_from_user(buf, user_buf, buf_size))
   2201		return -EFAULT;
   2202	if (sscanf(buf, "%u", &event_log_flag) != 1)
   2203		return -EFAULT;
   2204	if (event_log_flag == 1)
   2205		iwl_dump_nic_event_log(priv, true, NULL);
   2206
   2207	return count;
   2208}
   2209#endif
   2210
   2211static ssize_t iwl_dbgfs_calib_disabled_read(struct file *file,
   2212					 char __user *user_buf,
   2213					 size_t count, loff_t *ppos)
   2214{
   2215	struct iwl_priv *priv = file->private_data;
   2216	char buf[120];
   2217	int pos = 0;
   2218	const size_t bufsz = sizeof(buf);
   2219
   2220	pos += scnprintf(buf + pos, bufsz - pos,
   2221			 "Sensitivity calibrations %s\n",
   2222			 (priv->calib_disabled &
   2223					IWL_SENSITIVITY_CALIB_DISABLED) ?
   2224			 "DISABLED" : "ENABLED");
   2225	pos += scnprintf(buf + pos, bufsz - pos,
   2226			 "Chain noise calibrations %s\n",
   2227			 (priv->calib_disabled &
   2228					IWL_CHAIN_NOISE_CALIB_DISABLED) ?
   2229			 "DISABLED" : "ENABLED");
   2230	pos += scnprintf(buf + pos, bufsz - pos,
   2231			 "Tx power calibrations %s\n",
   2232			 (priv->calib_disabled &
   2233					IWL_TX_POWER_CALIB_DISABLED) ?
   2234			 "DISABLED" : "ENABLED");
   2235
   2236	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
   2237}
   2238
   2239static ssize_t iwl_dbgfs_calib_disabled_write(struct file *file,
   2240					      const char __user *user_buf,
   2241					      size_t count, loff_t *ppos)
   2242{
   2243	struct iwl_priv *priv = file->private_data;
   2244	char buf[8];
   2245	u32 calib_disabled;
   2246	int buf_size;
   2247
   2248	memset(buf, 0, sizeof(buf));
   2249	buf_size = min(count, sizeof(buf) - 1);
   2250	if (copy_from_user(buf, user_buf, buf_size))
   2251		return -EFAULT;
   2252	if (sscanf(buf, "%x", &calib_disabled) != 1)
   2253		return -EFAULT;
   2254
   2255	priv->calib_disabled = calib_disabled;
   2256
   2257	return count;
   2258}
   2259
   2260static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
   2261					  const char __user *user_buf,
   2262					  size_t count, loff_t *ppos)
   2263{
   2264	struct iwl_priv *priv = file->private_data;
   2265	bool fw_restart = iwlwifi_mod_params.fw_restart;
   2266	int __maybe_unused ret;
   2267
   2268	iwlwifi_mod_params.fw_restart = true;
   2269
   2270	mutex_lock(&priv->mutex);
   2271
   2272	/* take the return value to make compiler happy - it will fail anyway */
   2273	ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, 0, 0, NULL);
   2274
   2275	mutex_unlock(&priv->mutex);
   2276
   2277	iwlwifi_mod_params.fw_restart = fw_restart;
   2278
   2279	return count;
   2280}
   2281
   2282DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
   2283DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
   2284DEBUGFS_READ_FILE_OPS(ucode_general_stats);
   2285DEBUGFS_READ_FILE_OPS(sensitivity);
   2286DEBUGFS_READ_FILE_OPS(chain_noise);
   2287DEBUGFS_READ_FILE_OPS(power_save_status);
   2288DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
   2289DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
   2290DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
   2291DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
   2292DEBUGFS_READ_WRITE_FILE_OPS(rf_reset);
   2293DEBUGFS_READ_FILE_OPS(rxon_flags);
   2294DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
   2295DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
   2296DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
   2297DEBUGFS_READ_FILE_OPS(bt_traffic);
   2298DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
   2299DEBUGFS_READ_FILE_OPS(reply_tx_error);
   2300DEBUGFS_WRITE_FILE_OPS(echo_test);
   2301DEBUGFS_WRITE_FILE_OPS(fw_restart);
   2302#ifdef CONFIG_IWLWIFI_DEBUG
   2303DEBUGFS_READ_WRITE_FILE_OPS(log_event);
   2304#endif
   2305DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);
   2306
   2307/*
   2308 * Create the debugfs files and directories
   2309 *
   2310 */
   2311void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
   2312{
   2313	struct dentry *dir_data, *dir_rf, *dir_debug;
   2314
   2315	priv->debugfs_dir = dbgfs_dir;
   2316
   2317	dir_data = debugfs_create_dir("data", dbgfs_dir);
   2318	dir_rf = debugfs_create_dir("rf", dbgfs_dir);
   2319	dir_debug = debugfs_create_dir("debug", dbgfs_dir);
   2320
   2321	DEBUGFS_ADD_FILE(nvm, dir_data, 0400);
   2322	DEBUGFS_ADD_FILE(sram, dir_data, 0600);
   2323	DEBUGFS_ADD_FILE(wowlan_sram, dir_data, 0400);
   2324	DEBUGFS_ADD_FILE(stations, dir_data, 0400);
   2325	DEBUGFS_ADD_FILE(channels, dir_data, 0400);
   2326	DEBUGFS_ADD_FILE(status, dir_data, 0400);
   2327	DEBUGFS_ADD_FILE(rx_handlers, dir_data, 0600);
   2328	DEBUGFS_ADD_FILE(qos, dir_data, 0400);
   2329	DEBUGFS_ADD_FILE(sleep_level_override, dir_data, 0600);
   2330	DEBUGFS_ADD_FILE(current_sleep_command, dir_data, 0400);
   2331	DEBUGFS_ADD_FILE(thermal_throttling, dir_data, 0400);
   2332	DEBUGFS_ADD_FILE(disable_ht40, dir_data, 0600);
   2333	DEBUGFS_ADD_FILE(temperature, dir_data, 0400);
   2334
   2335	DEBUGFS_ADD_FILE(power_save_status, dir_debug, 0400);
   2336	DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, 0200);
   2337	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, 0200);
   2338	DEBUGFS_ADD_FILE(plcp_delta, dir_debug, 0600);
   2339	DEBUGFS_ADD_FILE(rf_reset, dir_debug, 0600);
   2340	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, 0400);
   2341	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, 0400);
   2342	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, 0400);
   2343	DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, 0200);
   2344	DEBUGFS_ADD_FILE(protection_mode, dir_debug, 0600);
   2345	DEBUGFS_ADD_FILE(sensitivity, dir_debug, 0400);
   2346	DEBUGFS_ADD_FILE(chain_noise, dir_debug, 0400);
   2347	DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, 0600);
   2348	DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, 0400);
   2349	DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, 0400);
   2350	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, 0200);
   2351	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, 0200);
   2352	DEBUGFS_ADD_FILE(echo_test, dir_debug, 0200);
   2353	DEBUGFS_ADD_FILE(fw_restart, dir_debug, 0200);
   2354#ifdef CONFIG_IWLWIFI_DEBUG
   2355	DEBUGFS_ADD_FILE(log_event, dir_debug, 0600);
   2356#endif
   2357
   2358	if (iwl_advanced_bt_coexist(priv))
   2359		DEBUGFS_ADD_FILE(bt_traffic, dir_debug, 0400);
   2360
   2361	/* Calibrations disabled/enabled status*/
   2362	DEBUGFS_ADD_FILE(calib_disabled, dir_rf, 0600);
   2363
   2364	/*
   2365	 * Create a symlink with mac80211. This is not very robust, as it does
   2366	 * not remove the symlink created. The implicit assumption is that
   2367	 * when the opmode exits, mac80211 will also exit, and will remove
   2368	 * this symlink as part of its cleanup.
   2369	 */
   2370	if (priv->mac80211_registered) {
   2371		char buf[100];
   2372		struct dentry *mac80211_dir, *dev_dir;
   2373
   2374		dev_dir = dbgfs_dir->d_parent;
   2375		mac80211_dir = priv->hw->wiphy->debugfsdir;
   2376
   2377		snprintf(buf, 100, "../../%pd2", dev_dir);
   2378
   2379		debugfs_create_symlink("iwlwifi", mac80211_dir, buf);
   2380	}
   2381}