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