brintos

brintos / linux-shallow public Read only

0
0
Text · 76.3 KiB · b246dbd Raw
2382 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/******************************************************************************3 *4 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.5 * Copyright (C) 2018 Intel Corporation6 *****************************************************************************/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		else113			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	else506		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 actually559	 * valid here. However, let's not confuse them and present560	 * 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 on692	 * the last statistics notification from uCode693	 * might not reflect the current uCode activity694	 */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 on1118	 * the last statistics notification from uCode1119	 * might not reflect the current uCode activity1120	 */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 on1318	 * the last statistics notification from uCode1319	 * might not reflect the current uCode activity1320	 */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 on1446	 * the last statistics notification from uCode1447	 * might not reflect the current uCode activity1448	 */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	else1941		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	else1981		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	else2106		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	else2132		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	else2148		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_DEBUG2170static 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#endif2210 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_DEBUG2303DEBUGFS_READ_WRITE_FILE_OPS(log_event);2304#endif2305DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);2306 2307/*2308 * Create the debugfs files and directories2309 *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_DEBUG2355	DEBUGFS_ADD_FILE(log_event, dir_debug, 0600);2356#endif2357 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 does2366	 * not remove the symlink created. The implicit assumption is that2367	 * when the opmode exits, mac80211 will also exit, and will remove2368	 * 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}2382