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