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