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