iwl-debugfs.c revision a9e1cb6a78ea8a74c49bf76726a2942f636a833b
1/******************************************************************************
2 *
3 * GPL LICENSE SUMMARY
4 *
5 * Copyright(c) 2008 - 2009 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/kernel.h>
30#include <linux/module.h>
31#include <linux/debugfs.h>
32
33#include <linux/ieee80211.h>
34#include <net/mac80211.h>
35
36
37#include "iwl-dev.h"
38#include "iwl-debug.h"
39#include "iwl-core.h"
40#include "iwl-io.h"
41#include "iwl-calib.h"
42
43/* create and remove of files */
44#define DEBUGFS_ADD_DIR(name, parent) do {                              \
45	dbgfs->dir_##name = debugfs_create_dir(#name, parent);          \
46	if (!(dbgfs->dir_##name))                                       \
47		goto err; 						\
48} while (0)
49
50#define DEBUGFS_ADD_FILE(name, parent, mode) do {                       \
51	dbgfs->dbgfs_##parent##_files.file_##name =                     \
52	debugfs_create_file(#name, mode,                                \
53				dbgfs->dir_##parent, priv,              \
54				&iwl_dbgfs_##name##_ops);               \
55	if (!(dbgfs->dbgfs_##parent##_files.file_##name))               \
56		goto err;                                               \
57} while (0)
58
59#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {                        \
60	dbgfs->dbgfs_##parent##_files.file_##name =                     \
61	debugfs_create_bool(#name, S_IWUSR | S_IRUSR,                   \
62			    dbgfs->dir_##parent, ptr);                  \
63	if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)		\
64			|| !dbgfs->dbgfs_##parent##_files.file_##name)	\
65		goto err;                                               \
66} while (0)
67
68#define DEBUGFS_ADD_X32(name, parent, ptr) do {                        \
69	dbgfs->dbgfs_##parent##_files.file_##name =                     \
70	debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr);   \
71	if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)		\
72			|| !dbgfs->dbgfs_##parent##_files.file_##name)	\
73		goto err;                                               \
74} while (0)
75
76#define DEBUGFS_REMOVE(name)  do {              \
77	debugfs_remove(name);                   \
78	name = NULL;                            \
79} while (0);
80
81/* file operation */
82#define DEBUGFS_READ_FUNC(name)                                         \
83static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
84					char __user *user_buf,          \
85					size_t count, loff_t *ppos);
86
87#define DEBUGFS_WRITE_FUNC(name)                                        \
88static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
89					const char __user *user_buf,    \
90					size_t count, loff_t *ppos);
91
92
93static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
94{
95	file->private_data = inode->i_private;
96	return 0;
97}
98
99#define DEBUGFS_READ_FILE_OPS(name)                                     \
100	DEBUGFS_READ_FUNC(name);                                        \
101static const struct file_operations iwl_dbgfs_##name##_ops = {          \
102	.read = iwl_dbgfs_##name##_read,                       		\
103	.open = iwl_dbgfs_open_file_generic,                    	\
104};
105
106#define DEBUGFS_WRITE_FILE_OPS(name)                                    \
107	DEBUGFS_WRITE_FUNC(name);                                       \
108static const struct file_operations iwl_dbgfs_##name##_ops = {          \
109	.write = iwl_dbgfs_##name##_write,                              \
110	.open = iwl_dbgfs_open_file_generic,                    	\
111};
112
113
114#define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \
115	DEBUGFS_READ_FUNC(name);                                        \
116	DEBUGFS_WRITE_FUNC(name);                                       \
117static const struct file_operations iwl_dbgfs_##name##_ops = {          \
118	.write = iwl_dbgfs_##name##_write,                              \
119	.read = iwl_dbgfs_##name##_read,                                \
120	.open = iwl_dbgfs_open_file_generic,                            \
121};
122
123
124static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
125						char __user *user_buf,
126						size_t count, loff_t *ppos) {
127
128	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
129	char *buf;
130	int pos = 0;
131
132	int cnt;
133	ssize_t ret;
134	const size_t bufsz = 100 +
135		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
136	buf = kzalloc(bufsz, GFP_KERNEL);
137	if (!buf)
138		return -ENOMEM;
139	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
140	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
141		pos += scnprintf(buf + pos, bufsz - pos,
142				 "\t%25s\t\t: %u\n",
143				 get_mgmt_string(cnt),
144				 priv->tx_stats.mgmt[cnt]);
145	}
146	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
147	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
148		pos += scnprintf(buf + pos, bufsz - pos,
149				 "\t%25s\t\t: %u\n",
150				 get_ctrl_string(cnt),
151				 priv->tx_stats.ctrl[cnt]);
152	}
153	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
154	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
155			 priv->tx_stats.data_cnt);
156	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
157			 priv->tx_stats.data_bytes);
158	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
159	kfree(buf);
160	return ret;
161}
162
163static ssize_t iwl_dbgfs_clear_traffic_statistics_write(struct file *file,
164					const char __user *user_buf,
165					size_t count, loff_t *ppos)
166{
167	struct iwl_priv *priv = file->private_data;
168	u32 clear_flag;
169	char buf[8];
170	int buf_size;
171
172	memset(buf, 0, sizeof(buf));
173	buf_size = min(count, sizeof(buf) -  1);
174	if (copy_from_user(buf, user_buf, buf_size))
175		return -EFAULT;
176	if (sscanf(buf, "%x", &clear_flag) != 1)
177		return -EFAULT;
178	iwl_clear_traffic_stats(priv);
179
180	return count;
181}
182
183static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
184						char __user *user_buf,
185						size_t count, loff_t *ppos) {
186
187	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
188	char *buf;
189	int pos = 0;
190	int cnt;
191	ssize_t ret;
192	const size_t bufsz = 100 +
193		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
194	buf = kzalloc(bufsz, GFP_KERNEL);
195	if (!buf)
196		return -ENOMEM;
197
198	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
199	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
200		pos += scnprintf(buf + pos, bufsz - pos,
201				 "\t%25s\t\t: %u\n",
202				 get_mgmt_string(cnt),
203				 priv->rx_stats.mgmt[cnt]);
204	}
205	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
206	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
207		pos += scnprintf(buf + pos, bufsz - pos,
208				 "\t%25s\t\t: %u\n",
209				 get_ctrl_string(cnt),
210				 priv->rx_stats.ctrl[cnt]);
211	}
212	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
213	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
214			 priv->rx_stats.data_cnt);
215	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
216			 priv->rx_stats.data_bytes);
217
218	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
219	kfree(buf);
220	return ret;
221}
222
223#define BYTE1_MASK 0x000000ff;
224#define BYTE2_MASK 0x0000ffff;
225#define BYTE3_MASK 0x00ffffff;
226static ssize_t iwl_dbgfs_sram_read(struct file *file,
227					char __user *user_buf,
228					size_t count, loff_t *ppos)
229{
230	u32 val;
231	char *buf;
232	ssize_t ret;
233	int i;
234	int pos = 0;
235	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
236	size_t bufsz;
237
238	/* default is to dump the entire data segment */
239	if (!priv->dbgfs->sram_offset && !priv->dbgfs->sram_len) {
240		priv->dbgfs->sram_offset = 0x800000;
241		if (priv->ucode_type == UCODE_INIT)
242			priv->dbgfs->sram_len = priv->ucode_init_data.len;
243		else
244			priv->dbgfs->sram_len = priv->ucode_data.len;
245	}
246	bufsz =  30 + priv->dbgfs->sram_len * sizeof(char) * 10;
247	buf = kmalloc(bufsz, GFP_KERNEL);
248	if (!buf)
249		return -ENOMEM;
250	pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
251			priv->dbgfs->sram_len);
252	pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
253			priv->dbgfs->sram_offset);
254	for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
255		val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
256					priv->dbgfs->sram_len - i);
257		if (i < 4) {
258			switch (i) {
259			case 1:
260				val &= BYTE1_MASK;
261				break;
262			case 2:
263				val &= BYTE2_MASK;
264				break;
265			case 3:
266				val &= BYTE3_MASK;
267				break;
268			}
269		}
270		if (!(i % 16))
271			pos += scnprintf(buf + pos, bufsz - pos, "\n");
272		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
273	}
274	pos += scnprintf(buf + pos, bufsz - pos, "\n");
275
276	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
277	kfree(buf);
278	return ret;
279}
280
281static ssize_t iwl_dbgfs_sram_write(struct file *file,
282					const char __user *user_buf,
283					size_t count, loff_t *ppos)
284{
285	struct iwl_priv *priv = file->private_data;
286	char buf[64];
287	int buf_size;
288	u32 offset, len;
289
290	memset(buf, 0, sizeof(buf));
291	buf_size = min(count, sizeof(buf) -  1);
292	if (copy_from_user(buf, user_buf, buf_size))
293		return -EFAULT;
294
295	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
296		priv->dbgfs->sram_offset = offset;
297		priv->dbgfs->sram_len = len;
298	} else {
299		priv->dbgfs->sram_offset = 0;
300		priv->dbgfs->sram_len = 0;
301	}
302
303	return count;
304}
305
306static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
307					size_t count, loff_t *ppos)
308{
309	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
310	struct iwl_station_entry *station;
311	int max_sta = priv->hw_params.max_stations;
312	char *buf;
313	int i, j, pos = 0;
314	ssize_t ret;
315	/* Add 30 for initial string */
316	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
317
318	buf = kmalloc(bufsz, GFP_KERNEL);
319	if (!buf)
320		return -ENOMEM;
321
322	pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
323			priv->num_stations);
324
325	for (i = 0; i < max_sta; i++) {
326		station = &priv->stations[i];
327		if (station->used) {
328			pos += scnprintf(buf + pos, bufsz - pos,
329					"station %d:\ngeneral data:\n", i+1);
330			pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
331					station->sta.sta.sta_id);
332			pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
333					station->sta.mode);
334			pos += scnprintf(buf + pos, bufsz - pos,
335					"flags: 0x%x\n",
336					station->sta.station_flags_msk);
337			pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
338			pos += scnprintf(buf + pos, bufsz - pos,
339					"seq_num\t\ttxq_id");
340			pos += scnprintf(buf + pos, bufsz - pos,
341					"\tframe_count\twait_for_ba\t");
342			pos += scnprintf(buf + pos, bufsz - pos,
343					"start_idx\tbitmap0\t");
344			pos += scnprintf(buf + pos, bufsz - pos,
345					"bitmap1\trate_n_flags");
346			pos += scnprintf(buf + pos, bufsz - pos, "\n");
347
348			for (j = 0; j < MAX_TID_COUNT; j++) {
349				pos += scnprintf(buf + pos, bufsz - pos,
350						"[%d]:\t\t%u", j,
351						station->tid[j].seq_number);
352				pos += scnprintf(buf + pos, bufsz - pos,
353						"\t%u\t\t%u\t\t%u\t\t",
354						station->tid[j].agg.txq_id,
355						station->tid[j].agg.frame_count,
356						station->tid[j].agg.wait_for_ba);
357				pos += scnprintf(buf + pos, bufsz - pos,
358						"%u\t%llu\t%u",
359						station->tid[j].agg.start_idx,
360						(unsigned long long)station->tid[j].agg.bitmap,
361						station->tid[j].agg.rate_n_flags);
362				pos += scnprintf(buf + pos, bufsz - pos, "\n");
363			}
364			pos += scnprintf(buf + pos, bufsz - pos, "\n");
365		}
366	}
367
368	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
369	kfree(buf);
370	return ret;
371}
372
373static ssize_t iwl_dbgfs_nvm_read(struct file *file,
374				       char __user *user_buf,
375				       size_t count,
376				       loff_t *ppos)
377{
378	ssize_t ret;
379	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
380	int pos = 0, ofs = 0, buf_size = 0;
381	const u8 *ptr;
382	char *buf;
383	u16 eeprom_ver;
384	size_t eeprom_len = priv->cfg->eeprom_size;
385	buf_size = 4 * eeprom_len + 256;
386
387	if (eeprom_len % 16) {
388		IWL_ERR(priv, "NVM size is not multiple of 16.\n");
389		return -ENODATA;
390	}
391
392	ptr = priv->eeprom;
393	if (!ptr) {
394		IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
395		return -ENOMEM;
396	}
397
398	/* 4 characters for byte 0xYY */
399	buf = kzalloc(buf_size, GFP_KERNEL);
400	if (!buf) {
401		IWL_ERR(priv, "Can not allocate Buffer\n");
402		return -ENOMEM;
403	}
404	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
405	pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
406			"version: 0x%x\n",
407			(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
408			 ? "OTP" : "EEPROM", eeprom_ver);
409	for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
410		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
411		hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
412				   buf_size - pos, 0);
413		pos += strlen(buf + pos);
414		if (buf_size - pos > 0)
415			buf[pos++] = '\n';
416	}
417
418	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
419	kfree(buf);
420	return ret;
421}
422
423static ssize_t iwl_dbgfs_log_event_write(struct file *file,
424					const char __user *user_buf,
425					size_t count, loff_t *ppos)
426{
427	struct iwl_priv *priv = file->private_data;
428	u32 event_log_flag;
429	char buf[8];
430	int buf_size;
431
432	memset(buf, 0, sizeof(buf));
433	buf_size = min(count, sizeof(buf) -  1);
434	if (copy_from_user(buf, user_buf, buf_size))
435		return -EFAULT;
436	if (sscanf(buf, "%d", &event_log_flag) != 1)
437		return -EFAULT;
438	if (event_log_flag == 1)
439		priv->cfg->ops->lib->dump_nic_event_log(priv, true);
440
441	return count;
442}
443
444
445
446static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
447				       size_t count, loff_t *ppos)
448{
449	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
450	struct ieee80211_channel *channels = NULL;
451	const struct ieee80211_supported_band *supp_band = NULL;
452	int pos = 0, i, bufsz = PAGE_SIZE;
453	char *buf;
454	ssize_t ret;
455
456	if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
457		return -EAGAIN;
458
459	buf = kzalloc(bufsz, GFP_KERNEL);
460	if (!buf) {
461		IWL_ERR(priv, "Can not allocate Buffer\n");
462		return -ENOMEM;
463	}
464
465	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
466	if (supp_band) {
467		channels = supp_band->channels;
468
469		pos += scnprintf(buf + pos, bufsz - pos,
470				"Displaying %d channels in 2.4GHz band 802.11bg):\n",
471				supp_band->n_channels);
472
473		for (i = 0; i < supp_band->n_channels; i++)
474			pos += scnprintf(buf + pos, bufsz - pos,
475					"%d: %ddBm: BSS%s%s, %s.\n",
476					ieee80211_frequency_to_channel(
477					channels[i].center_freq),
478					channels[i].max_power,
479					channels[i].flags & IEEE80211_CHAN_RADAR ?
480					" (IEEE 802.11h required)" : "",
481					((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
482					|| (channels[i].flags &
483					IEEE80211_CHAN_RADAR)) ? "" :
484					", IBSS",
485					channels[i].flags &
486					IEEE80211_CHAN_PASSIVE_SCAN ?
487					"passive only" : "active/passive");
488	}
489	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
490	if (supp_band) {
491		channels = supp_band->channels;
492
493		pos += scnprintf(buf + pos, bufsz - pos,
494				"Displaying %d channels in 5.2GHz band (802.11a)\n",
495				supp_band->n_channels);
496
497		for (i = 0; i < supp_band->n_channels; i++)
498			pos += scnprintf(buf + pos, bufsz - pos,
499					"%d: %ddBm: BSS%s%s, %s.\n",
500					ieee80211_frequency_to_channel(
501					channels[i].center_freq),
502					channels[i].max_power,
503					channels[i].flags & IEEE80211_CHAN_RADAR ?
504					" (IEEE 802.11h required)" : "",
505					((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
506					|| (channels[i].flags &
507					IEEE80211_CHAN_RADAR)) ? "" :
508					", IBSS",
509					channels[i].flags &
510					IEEE80211_CHAN_PASSIVE_SCAN ?
511					"passive only" : "active/passive");
512	}
513	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
514	kfree(buf);
515	return ret;
516}
517
518static ssize_t iwl_dbgfs_status_read(struct file *file,
519						char __user *user_buf,
520						size_t count, loff_t *ppos) {
521
522	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
523	char buf[512];
524	int pos = 0;
525	const size_t bufsz = sizeof(buf);
526
527	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
528		test_bit(STATUS_HCMD_ACTIVE, &priv->status));
529	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
530		test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
531	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
532		test_bit(STATUS_INT_ENABLED, &priv->status));
533	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
534		test_bit(STATUS_RF_KILL_HW, &priv->status));
535	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
536		test_bit(STATUS_CT_KILL, &priv->status));
537	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
538		test_bit(STATUS_INIT, &priv->status));
539	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
540		test_bit(STATUS_ALIVE, &priv->status));
541	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
542		test_bit(STATUS_READY, &priv->status));
543	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
544		test_bit(STATUS_TEMPERATURE, &priv->status));
545	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
546		test_bit(STATUS_GEO_CONFIGURED, &priv->status));
547	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
548		test_bit(STATUS_EXIT_PENDING, &priv->status));
549	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
550		test_bit(STATUS_STATISTICS, &priv->status));
551	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
552		test_bit(STATUS_SCANNING, &priv->status));
553	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
554		test_bit(STATUS_SCAN_ABORTING, &priv->status));
555	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
556		test_bit(STATUS_SCAN_HW, &priv->status));
557	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
558		test_bit(STATUS_POWER_PMI, &priv->status));
559	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
560		test_bit(STATUS_FW_ERROR, &priv->status));
561	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n",
562		test_bit(STATUS_MODE_PENDING, &priv->status));
563	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
564}
565
566static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
567					char __user *user_buf,
568					size_t count, loff_t *ppos) {
569
570	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
571	int pos = 0;
572	int cnt = 0;
573	char *buf;
574	int bufsz = 24 * 64; /* 24 items * 64 char per item */
575	ssize_t ret;
576
577	buf = kzalloc(bufsz, GFP_KERNEL);
578	if (!buf) {
579		IWL_ERR(priv, "Can not allocate Buffer\n");
580		return -ENOMEM;
581	}
582
583	pos += scnprintf(buf + pos, bufsz - pos,
584			"Interrupt Statistics Report:\n");
585
586	pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
587		priv->isr_stats.hw);
588	pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
589		priv->isr_stats.sw);
590	if (priv->isr_stats.sw > 0) {
591		pos += scnprintf(buf + pos, bufsz - pos,
592			"\tLast Restarting Code:  0x%X\n",
593			priv->isr_stats.sw_err);
594	}
595#ifdef CONFIG_IWLWIFI_DEBUG
596	pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
597		priv->isr_stats.sch);
598	pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
599		priv->isr_stats.alive);
600#endif
601	pos += scnprintf(buf + pos, bufsz - pos,
602		"HW RF KILL switch toggled:\t %u\n",
603		priv->isr_stats.rfkill);
604
605	pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
606		priv->isr_stats.ctkill);
607
608	pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
609		priv->isr_stats.wakeup);
610
611	pos += scnprintf(buf + pos, bufsz - pos,
612		"Rx command responses:\t\t %u\n",
613		priv->isr_stats.rx);
614	for (cnt = 0; cnt < REPLY_MAX; cnt++) {
615		if (priv->isr_stats.rx_handlers[cnt] > 0)
616			pos += scnprintf(buf + pos, bufsz - pos,
617				"\tRx handler[%36s]:\t\t %u\n",
618				get_cmd_string(cnt),
619				priv->isr_stats.rx_handlers[cnt]);
620	}
621
622	pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
623		priv->isr_stats.tx);
624
625	pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
626		priv->isr_stats.unhandled);
627
628	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
629	kfree(buf);
630	return ret;
631}
632
633static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
634					 const char __user *user_buf,
635					 size_t count, loff_t *ppos)
636{
637	struct iwl_priv *priv = file->private_data;
638	char buf[8];
639	int buf_size;
640	u32 reset_flag;
641
642	memset(buf, 0, sizeof(buf));
643	buf_size = min(count, sizeof(buf) -  1);
644	if (copy_from_user(buf, user_buf, buf_size))
645		return -EFAULT;
646	if (sscanf(buf, "%x", &reset_flag) != 1)
647		return -EFAULT;
648	if (reset_flag == 0)
649		iwl_clear_isr_stats(priv);
650
651	return count;
652}
653
654static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
655				       size_t count, loff_t *ppos)
656{
657	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
658	int pos = 0, i;
659	char buf[256];
660	const size_t bufsz = sizeof(buf);
661	ssize_t ret;
662
663	for (i = 0; i < AC_NUM; i++) {
664		pos += scnprintf(buf + pos, bufsz - pos,
665			"\tcw_min\tcw_max\taifsn\ttxop\n");
666		pos += scnprintf(buf + pos, bufsz - pos,
667				"AC[%d]\t%u\t%u\t%u\t%u\n", i,
668				priv->qos_data.def_qos_parm.ac[i].cw_min,
669				priv->qos_data.def_qos_parm.ac[i].cw_max,
670				priv->qos_data.def_qos_parm.ac[i].aifsn,
671				priv->qos_data.def_qos_parm.ac[i].edca_txop);
672	}
673	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
674	return ret;
675}
676
677static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
678				  size_t count, loff_t *ppos)
679{
680	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
681	int pos = 0;
682	char buf[256];
683	const size_t bufsz = sizeof(buf);
684	ssize_t ret;
685
686	pos += scnprintf(buf + pos, bufsz - pos,
687			 "allow blinking: %s\n",
688			 (priv->allow_blinking) ? "True" : "False");
689	if (priv->allow_blinking) {
690		pos += scnprintf(buf + pos, bufsz - pos,
691				 "Led blinking rate: %u\n",
692				 priv->last_blink_rate);
693		pos += scnprintf(buf + pos, bufsz - pos,
694				 "Last blink time: %lu\n",
695				 priv->last_blink_time);
696	}
697
698	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
699	return ret;
700}
701
702static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
703				char __user *user_buf,
704				size_t count, loff_t *ppos)
705{
706	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
707	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
708	struct iwl_tt_restriction *restriction;
709	char buf[100];
710	int pos = 0;
711	const size_t bufsz = sizeof(buf);
712	ssize_t ret;
713
714	pos += scnprintf(buf + pos, bufsz - pos,
715			"Thermal Throttling Mode: %s\n",
716			tt->advanced_tt ? "Advance" : "Legacy");
717	pos += scnprintf(buf + pos, bufsz - pos,
718			"Thermal Throttling State: %d\n",
719			tt->state);
720	if (tt->advanced_tt) {
721		restriction = tt->restriction + tt->state;
722		pos += scnprintf(buf + pos, bufsz - pos,
723				"Tx mode: %d\n",
724				restriction->tx_stream);
725		pos += scnprintf(buf + pos, bufsz - pos,
726				"Rx mode: %d\n",
727				restriction->rx_stream);
728		pos += scnprintf(buf + pos, bufsz - pos,
729				"HT mode: %d\n",
730				restriction->is_ht);
731	}
732	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
733	return ret;
734}
735
736static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
737					 const char __user *user_buf,
738					 size_t count, loff_t *ppos)
739{
740	struct iwl_priv *priv = file->private_data;
741	char buf[8];
742	int buf_size;
743	int ht40;
744
745	memset(buf, 0, sizeof(buf));
746	buf_size = min(count, sizeof(buf) -  1);
747	if (copy_from_user(buf, user_buf, buf_size))
748		return -EFAULT;
749	if (sscanf(buf, "%d", &ht40) != 1)
750		return -EFAULT;
751	if (!iwl_is_associated(priv))
752		priv->disable_ht40 = ht40 ? true : false;
753	else {
754		IWL_ERR(priv, "Sta associated with AP - "
755			"Change to 40MHz channel support is not allowed\n");
756		return -EINVAL;
757	}
758
759	return count;
760}
761
762static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
763					 char __user *user_buf,
764					 size_t count, loff_t *ppos)
765{
766	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
767	char buf[100];
768	int pos = 0;
769	const size_t bufsz = sizeof(buf);
770	ssize_t ret;
771
772	pos += scnprintf(buf + pos, bufsz - pos,
773			"11n 40MHz Mode: %s\n",
774			priv->disable_ht40 ? "Disabled" : "Enabled");
775	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
776	return ret;
777}
778
779static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
780						    const char __user *user_buf,
781						    size_t count, loff_t *ppos)
782{
783	struct iwl_priv *priv = file->private_data;
784	char buf[8];
785	int buf_size;
786	int value;
787
788	memset(buf, 0, sizeof(buf));
789	buf_size = min(count, sizeof(buf) -  1);
790	if (copy_from_user(buf, user_buf, buf_size))
791		return -EFAULT;
792
793	if (sscanf(buf, "%d", &value) != 1)
794		return -EINVAL;
795
796	/*
797	 * Our users expect 0 to be "CAM", but 0 isn't actually
798	 * valid here. However, let's not confuse them and present
799	 * IWL_POWER_INDEX_1 as "1", not "0".
800	 */
801	if (value == 0)
802		return -EINVAL;
803	else if (value > 0)
804		value -= 1;
805
806	if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
807		return -EINVAL;
808
809	if (!iwl_is_ready_rf(priv))
810		return -EAGAIN;
811
812	priv->power_data.debug_sleep_level_override = value;
813
814	iwl_power_update_mode(priv, true);
815
816	return count;
817}
818
819static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
820						   char __user *user_buf,
821						   size_t count, loff_t *ppos)
822{
823	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
824	char buf[10];
825	int pos, value;
826	const size_t bufsz = sizeof(buf);
827
828	/* see the write function */
829	value = priv->power_data.debug_sleep_level_override;
830	if (value >= 0)
831		value += 1;
832
833	pos = scnprintf(buf, bufsz, "%d\n", value);
834	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
835}
836
837static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
838						    char __user *user_buf,
839						    size_t count, loff_t *ppos)
840{
841	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
842	char buf[200];
843	int pos = 0, i;
844	const size_t bufsz = sizeof(buf);
845	struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
846
847	pos += scnprintf(buf + pos, bufsz - pos,
848			 "flags: %#.2x\n", le16_to_cpu(cmd->flags));
849	pos += scnprintf(buf + pos, bufsz - pos,
850			 "RX/TX timeout: %d/%d usec\n",
851			 le32_to_cpu(cmd->rx_data_timeout),
852			 le32_to_cpu(cmd->tx_data_timeout));
853	for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
854		pos += scnprintf(buf + pos, bufsz - pos,
855				 "sleep_interval[%d]: %d\n", i,
856				 le32_to_cpu(cmd->sleep_interval[i]));
857
858	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
859}
860
861DEBUGFS_READ_WRITE_FILE_OPS(sram);
862DEBUGFS_WRITE_FILE_OPS(log_event);
863DEBUGFS_READ_FILE_OPS(nvm);
864DEBUGFS_READ_FILE_OPS(stations);
865DEBUGFS_READ_FILE_OPS(channels);
866DEBUGFS_READ_FILE_OPS(status);
867DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
868DEBUGFS_READ_FILE_OPS(qos);
869DEBUGFS_READ_FILE_OPS(led);
870DEBUGFS_READ_FILE_OPS(thermal_throttling);
871DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
872DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
873DEBUGFS_READ_FILE_OPS(current_sleep_command);
874
875static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
876					 char __user *user_buf,
877					 size_t count, loff_t *ppos)
878{
879	struct iwl_priv *priv = file->private_data;
880	int pos = 0, ofs = 0;
881	int cnt = 0, entry;
882	struct iwl_tx_queue *txq;
883	struct iwl_queue *q;
884	struct iwl_rx_queue *rxq = &priv->rxq;
885	char *buf;
886	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
887		(priv->cfg->num_of_queues * 32 * 8) + 400;
888	const u8 *ptr;
889	ssize_t ret;
890
891	if (!priv->txq) {
892		IWL_ERR(priv, "txq not ready\n");
893		return -EAGAIN;
894	}
895	buf = kzalloc(bufsz, GFP_KERNEL);
896	if (!buf) {
897		IWL_ERR(priv, "Can not allocate buffer\n");
898		return -ENOMEM;
899	}
900	pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
901	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
902		txq = &priv->txq[cnt];
903		q = &txq->q;
904		pos += scnprintf(buf + pos, bufsz - pos,
905				"q[%d]: read_ptr: %u, write_ptr: %u\n",
906				cnt, q->read_ptr, q->write_ptr);
907	}
908	if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
909		ptr = priv->tx_traffic;
910		pos += scnprintf(buf + pos, bufsz - pos,
911				"Tx Traffic idx: %u\n",	priv->tx_traffic_idx);
912		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
913			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
914			     entry++,  ofs += 16) {
915				pos += scnprintf(buf + pos, bufsz - pos,
916						"0x%.4x ", ofs);
917				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
918						   buf + pos, bufsz - pos, 0);
919				pos += strlen(buf + pos);
920				if (bufsz - pos > 0)
921					buf[pos++] = '\n';
922			}
923		}
924	}
925
926	pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
927	pos += scnprintf(buf + pos, bufsz - pos,
928			"read: %u, write: %u\n",
929			 rxq->read, rxq->write);
930
931	if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
932		ptr = priv->rx_traffic;
933		pos += scnprintf(buf + pos, bufsz - pos,
934				"Rx Traffic idx: %u\n",	priv->rx_traffic_idx);
935		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
936			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
937			     entry++,  ofs += 16) {
938				pos += scnprintf(buf + pos, bufsz - pos,
939						"0x%.4x ", ofs);
940				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
941						   buf + pos, bufsz - pos, 0);
942				pos += strlen(buf + pos);
943				if (bufsz - pos > 0)
944					buf[pos++] = '\n';
945			}
946		}
947	}
948
949	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
950	kfree(buf);
951	return ret;
952}
953
954static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
955					 const char __user *user_buf,
956					 size_t count, loff_t *ppos)
957{
958	struct iwl_priv *priv = file->private_data;
959	char buf[8];
960	int buf_size;
961	int traffic_log;
962
963	memset(buf, 0, sizeof(buf));
964	buf_size = min(count, sizeof(buf) -  1);
965	if (copy_from_user(buf, user_buf, buf_size))
966		return -EFAULT;
967	if (sscanf(buf, "%d", &traffic_log) != 1)
968		return -EFAULT;
969	if (traffic_log == 0)
970		iwl_reset_traffic_log(priv);
971
972	return count;
973}
974
975static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
976						char __user *user_buf,
977						size_t count, loff_t *ppos) {
978
979	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
980	struct iwl_tx_queue *txq;
981	struct iwl_queue *q;
982	char *buf;
983	int pos = 0;
984	int cnt;
985	int ret;
986	const size_t bufsz = sizeof(char) * 64 * priv->cfg->num_of_queues;
987
988	if (!priv->txq) {
989		IWL_ERR(priv, "txq not ready\n");
990		return -EAGAIN;
991	}
992	buf = kzalloc(bufsz, GFP_KERNEL);
993	if (!buf)
994		return -ENOMEM;
995
996	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
997		txq = &priv->txq[cnt];
998		q = &txq->q;
999		pos += scnprintf(buf + pos, bufsz - pos,
1000				"hwq %.2d: read=%u write=%u stop=%d"
1001				" swq_id=%#.2x (ac %d/hwq %d)\n",
1002				cnt, q->read_ptr, q->write_ptr,
1003				!!test_bit(cnt, priv->queue_stopped),
1004				txq->swq_id,
1005				txq->swq_id & 0x80 ? txq->swq_id & 3 :
1006				txq->swq_id,
1007				txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
1008				0x1f : txq->swq_id);
1009		if (cnt >= 4)
1010			continue;
1011		/* for the ACs, display the stop count too */
1012		pos += scnprintf(buf + pos, bufsz - pos,
1013				"        stop-count: %d\n",
1014				atomic_read(&priv->queue_stop_count[cnt]));
1015	}
1016	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1017	kfree(buf);
1018	return ret;
1019}
1020
1021static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
1022						char __user *user_buf,
1023						size_t count, loff_t *ppos) {
1024
1025	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1026	struct iwl_rx_queue *rxq = &priv->rxq;
1027	char buf[256];
1028	int pos = 0;
1029	const size_t bufsz = sizeof(buf);
1030
1031	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
1032						rxq->read);
1033	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
1034						rxq->write);
1035	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
1036						rxq->free_count);
1037	pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
1038			 le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
1039	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1040}
1041
1042static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
1043				     int bufsz)
1044{
1045	int p = 0;
1046
1047	p += scnprintf(buf + p, bufsz - p,
1048		"Statistics Flag(0x%X):\n",
1049		le32_to_cpu(priv->statistics.flag));
1050	if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
1051		p += scnprintf(buf + p, bufsz - p,
1052		"\tStatistics have been cleared\n");
1053	p += scnprintf(buf + p, bufsz - p,
1054		"\tOperational Frequency: %s\n",
1055		(le32_to_cpu(priv->statistics.flag) &
1056		UCODE_STATISTICS_FREQUENCY_MSK)
1057		 ? "2.4 GHz" : "5.2 GHz");
1058	p += scnprintf(buf + p, bufsz - p,
1059		"\tTGj Narrow Band: %s\n",
1060		(le32_to_cpu(priv->statistics.flag) &
1061		UCODE_STATISTICS_NARROW_BAND_MSK)
1062		 ? "enabled" : "disabled");
1063	return p;
1064}
1065
1066
1067static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
1068					char __user *user_buf,
1069					size_t count, loff_t *ppos)
1070{
1071	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1072	int pos = 0;
1073	char *buf;
1074	int bufsz = sizeof(struct statistics_rx_phy) * 20 +
1075		sizeof(struct statistics_rx_non_phy) * 20 +
1076		sizeof(struct statistics_rx_ht_phy) * 20 + 400;
1077	ssize_t ret;
1078	struct statistics_rx_phy *ofdm, *accum_ofdm;
1079	struct statistics_rx_phy *cck, *accum_cck;
1080	struct statistics_rx_non_phy *general, *accum_general;
1081	struct statistics_rx_ht_phy *ht, *accum_ht;
1082
1083	if (!iwl_is_alive(priv))
1084		return -EAGAIN;
1085
1086	/* make request to uCode to retrieve statistics information */
1087	mutex_lock(&priv->mutex);
1088	ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1089	mutex_unlock(&priv->mutex);
1090
1091	if (ret) {
1092		IWL_ERR(priv,
1093			"Error sending statistics request: %zd\n", ret);
1094		return -EAGAIN;
1095	}
1096	buf = kzalloc(bufsz, GFP_KERNEL);
1097	if (!buf) {
1098		IWL_ERR(priv, "Can not allocate Buffer\n");
1099		return -ENOMEM;
1100	}
1101
1102	/* the statistic information display here is based on
1103	 * the last statistics notification from uCode
1104	 * might not reflect the current uCode activity
1105	 */
1106	ofdm = &priv->statistics.rx.ofdm;
1107	cck = &priv->statistics.rx.cck;
1108	general = &priv->statistics.rx.general;
1109	ht = &priv->statistics.rx.ofdm_ht;
1110	accum_ofdm = &priv->accum_statistics.rx.ofdm;
1111	accum_cck = &priv->accum_statistics.rx.cck;
1112	accum_general = &priv->accum_statistics.rx.general;
1113	accum_ht = &priv->accum_statistics.rx.ofdm_ht;
1114	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1115	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
1116	pos += scnprintf(buf + pos, bufsz - pos,
1117			"\t\t\tcurrent\t\t\taccumulative\n");
1118	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
1119			 le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt);
1120	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
1121			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt);
1122	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
1123			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err);
1124	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
1125			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err);
1126	pos += scnprintf(buf + pos, bufsz - pos,
1127			 "overrun_err:\t\t%u\t\t\t%u\n",
1128			 le32_to_cpu(ofdm->overrun_err),
1129			 accum_ofdm->overrun_err);
1130	pos += scnprintf(buf + pos, bufsz - pos,
1131			 "early_overrun_err:\t%u\t\t\t%u\n",
1132			 le32_to_cpu(ofdm->early_overrun_err),
1133			 accum_ofdm->early_overrun_err);
1134	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
1135			 le32_to_cpu(ofdm->crc32_good),
1136			 accum_ofdm->crc32_good);
1137	pos += scnprintf(buf + pos, bufsz - pos,
1138			 "false_alarm_cnt:\t%u\t\t\t%u\n",
1139			 le32_to_cpu(ofdm->false_alarm_cnt),
1140			 accum_ofdm->false_alarm_cnt);
1141	pos += scnprintf(buf + pos, bufsz - pos,
1142			 "fina_sync_err_cnt:\t%u\t\t\t%u\n",
1143			 le32_to_cpu(ofdm->fina_sync_err_cnt),
1144			 accum_ofdm->fina_sync_err_cnt);
1145	pos += scnprintf(buf + pos, bufsz - pos,
1146			 "sfd_timeout:\t\t%u\t\t\t%u\n",
1147			 le32_to_cpu(ofdm->sfd_timeout),
1148			 accum_ofdm->sfd_timeout);
1149	pos += scnprintf(buf + pos, bufsz - pos,
1150			 "fina_timeout:\t\t%u\t\t\t%u\n",
1151			 le32_to_cpu(ofdm->fina_timeout),
1152			 accum_ofdm->fina_timeout);
1153	pos += scnprintf(buf + pos, bufsz - pos,
1154			 "unresponded_rts:\t%u\t\t\t%u\n",
1155			 le32_to_cpu(ofdm->unresponded_rts),
1156			 accum_ofdm->unresponded_rts);
1157	pos += scnprintf(buf + pos, bufsz - pos,
1158			"rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
1159			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
1160			 accum_ofdm->rxe_frame_limit_overrun);
1161	pos += scnprintf(buf + pos, bufsz - pos,
1162			 "sent_ack_cnt:\t\t%u\t\t\t%u\n",
1163			 le32_to_cpu(ofdm->sent_ack_cnt),
1164			 accum_ofdm->sent_ack_cnt);
1165	pos += scnprintf(buf + pos, bufsz - pos,
1166			 "sent_cts_cnt:\t\t%u\t\t\t%u\n",
1167			 le32_to_cpu(ofdm->sent_cts_cnt),
1168			 accum_ofdm->sent_cts_cnt);
1169	pos += scnprintf(buf + pos, bufsz - pos,
1170			 "sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
1171			 le32_to_cpu(ofdm->sent_ba_rsp_cnt),
1172			 accum_ofdm->sent_ba_rsp_cnt);
1173	pos += scnprintf(buf + pos, bufsz - pos,
1174			 "dsp_self_kill:\t\t%u\t\t\t%u\n",
1175			 le32_to_cpu(ofdm->dsp_self_kill),
1176			 accum_ofdm->dsp_self_kill);
1177	pos += scnprintf(buf + pos, bufsz - pos,
1178			 "mh_format_err:\t\t%u\t\t\t%u\n",
1179			 le32_to_cpu(ofdm->mh_format_err),
1180			 accum_ofdm->mh_format_err);
1181	pos += scnprintf(buf + pos, bufsz - pos,
1182			 "re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
1183			 le32_to_cpu(ofdm->re_acq_main_rssi_sum),
1184			 accum_ofdm->re_acq_main_rssi_sum);
1185
1186	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
1187	pos += scnprintf(buf + pos, bufsz - pos,
1188			"\t\t\tcurrent\t\t\taccumulative\n");
1189	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
1190			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt);
1191	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
1192			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt);
1193	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
1194			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err);
1195	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
1196			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err);
1197	pos += scnprintf(buf + pos, bufsz - pos,
1198			 "overrun_err:\t\t%u\t\t\t%u\n",
1199			 le32_to_cpu(cck->overrun_err),
1200			 accum_cck->overrun_err);
1201	pos += scnprintf(buf + pos, bufsz - pos,
1202			 "early_overrun_err:\t%u\t\t\t%u\n",
1203			 le32_to_cpu(cck->early_overrun_err),
1204			 accum_cck->early_overrun_err);
1205	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
1206			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good);
1207	pos += scnprintf(buf + pos, bufsz - pos,
1208			 "false_alarm_cnt:\t%u\t\t\t%u\n",
1209			 le32_to_cpu(cck->false_alarm_cnt),
1210			 accum_cck->false_alarm_cnt);
1211	pos += scnprintf(buf + pos, bufsz - pos,
1212			 "fina_sync_err_cnt:\t%u\t\t\t%u\n",
1213			 le32_to_cpu(cck->fina_sync_err_cnt),
1214			 accum_cck->fina_sync_err_cnt);
1215	pos += scnprintf(buf + pos, bufsz - pos,
1216			 "sfd_timeout:\t\t%u\t\t\t%u\n",
1217			 le32_to_cpu(cck->sfd_timeout),
1218			 accum_cck->sfd_timeout);
1219	pos += scnprintf(buf + pos, bufsz - pos,
1220			 "fina_timeout:\t\t%u\t\t\t%u\n",
1221			 le32_to_cpu(cck->fina_timeout),
1222			 accum_cck->fina_timeout);
1223	pos += scnprintf(buf + pos, bufsz - pos,
1224			 "unresponded_rts:\t%u\t\t\t%u\n",
1225			 le32_to_cpu(cck->unresponded_rts),
1226			 accum_cck->unresponded_rts);
1227	pos += scnprintf(buf + pos, bufsz - pos,
1228			"rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
1229			 le32_to_cpu(cck->rxe_frame_limit_overrun),
1230			 accum_cck->rxe_frame_limit_overrun);
1231	pos += scnprintf(buf + pos, bufsz - pos,
1232			 "sent_ack_cnt:\t\t%u\t\t\t%u\n",
1233			 le32_to_cpu(cck->sent_ack_cnt),
1234			 accum_cck->sent_ack_cnt);
1235	pos += scnprintf(buf + pos, bufsz - pos,
1236			 "sent_cts_cnt:\t\t%u\t\t\t%u\n",
1237			 le32_to_cpu(cck->sent_cts_cnt),
1238			 accum_cck->sent_cts_cnt);
1239	pos += scnprintf(buf + pos, bufsz - pos,
1240			 "sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
1241			 le32_to_cpu(cck->sent_ba_rsp_cnt),
1242			 accum_cck->sent_ba_rsp_cnt);
1243	pos += scnprintf(buf + pos, bufsz - pos,
1244			 "dsp_self_kill:\t\t%u\t\t\t%u\n",
1245			 le32_to_cpu(cck->dsp_self_kill),
1246			 accum_cck->dsp_self_kill);
1247	pos += scnprintf(buf + pos, bufsz - pos,
1248			 "mh_format_err:\t\t%u\t\t\t%u\n",
1249			 le32_to_cpu(cck->mh_format_err),
1250			 accum_cck->mh_format_err);
1251	pos += scnprintf(buf + pos, bufsz - pos,
1252			 "re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
1253			 le32_to_cpu(cck->re_acq_main_rssi_sum),
1254			 accum_cck->re_acq_main_rssi_sum);
1255
1256	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
1257	pos += scnprintf(buf + pos, bufsz - pos,
1258			"\t\t\tcurrent\t\t\taccumulative\n");
1259	pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n",
1260			 le32_to_cpu(general->bogus_cts),
1261			 accum_general->bogus_cts);
1262	pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n",
1263			 le32_to_cpu(general->bogus_ack),
1264			 accum_general->bogus_ack);
1265	pos += scnprintf(buf + pos, bufsz - pos,
1266			 "non_bssid_frames:\t%u\t\t\t%u\n",
1267			 le32_to_cpu(general->non_bssid_frames),
1268			 accum_general->non_bssid_frames);
1269	pos += scnprintf(buf + pos, bufsz - pos,
1270			 "filtered_frames:\t%u\t\t\t%u\n",
1271			 le32_to_cpu(general->filtered_frames),
1272			 accum_general->filtered_frames);
1273	pos += scnprintf(buf + pos, bufsz - pos,
1274			 "non_channel_beacons:\t%u\t\t\t%u\n",
1275			 le32_to_cpu(general->non_channel_beacons),
1276			 accum_general->non_channel_beacons);
1277	pos += scnprintf(buf + pos, bufsz - pos,
1278			 "channel_beacons:\t%u\t\t\t%u\n",
1279			 le32_to_cpu(general->channel_beacons),
1280			 accum_general->channel_beacons);
1281	pos += scnprintf(buf + pos, bufsz - pos,
1282			 "num_missed_bcon:\t%u\t\t\t%u\n",
1283			 le32_to_cpu(general->num_missed_bcon),
1284			 accum_general->num_missed_bcon);
1285	pos += scnprintf(buf + pos, bufsz - pos,
1286			"adc_rx_saturation_time:\t%u\t\t\t%u\n",
1287			 le32_to_cpu(general->adc_rx_saturation_time),
1288			 accum_general->adc_rx_saturation_time);
1289	pos += scnprintf(buf + pos, bufsz - pos,
1290			"ina_detect_search_tm:\t%u\t\t\t%u\n",
1291			 le32_to_cpu(general->ina_detection_search_time),
1292			 accum_general->ina_detection_search_time);
1293	pos += scnprintf(buf + pos, bufsz - pos,
1294			 "beacon_silence_rssi_a:\t%u\t\t\t%u\n",
1295			 le32_to_cpu(general->beacon_silence_rssi_a),
1296			 accum_general->beacon_silence_rssi_a);
1297	pos += scnprintf(buf + pos, bufsz - pos,
1298			 "beacon_silence_rssi_b:\t%u\t\t\t%u\n",
1299			 le32_to_cpu(general->beacon_silence_rssi_b),
1300			 accum_general->beacon_silence_rssi_b);
1301	pos += scnprintf(buf + pos, bufsz - pos,
1302			 "beacon_silence_rssi_c:\t%u\t\t\t%u\n",
1303			 le32_to_cpu(general->beacon_silence_rssi_c),
1304			 accum_general->beacon_silence_rssi_c);
1305	pos += scnprintf(buf + pos, bufsz - pos,
1306			"interference_data_flag:\t%u\t\t\t%u\n",
1307			 le32_to_cpu(general->interference_data_flag),
1308			 accum_general->interference_data_flag);
1309	pos += scnprintf(buf + pos, bufsz - pos,
1310			 "channel_load:\t\t%u\t\t\t%u\n",
1311			 le32_to_cpu(general->channel_load),
1312			 accum_general->channel_load);
1313	pos += scnprintf(buf + pos, bufsz - pos,
1314			 "dsp_false_alarms:\t%u\t\t\t%u\n",
1315			 le32_to_cpu(general->dsp_false_alarms),
1316			 accum_general->dsp_false_alarms);
1317	pos += scnprintf(buf + pos, bufsz - pos,
1318			 "beacon_rssi_a:\t\t%u\t\t\t%u\n",
1319			 le32_to_cpu(general->beacon_rssi_a),
1320			 accum_general->beacon_rssi_a);
1321	pos += scnprintf(buf + pos, bufsz - pos,
1322			 "beacon_rssi_b:\t\t%u\t\t\t%u\n",
1323			 le32_to_cpu(general->beacon_rssi_b),
1324			 accum_general->beacon_rssi_b);
1325	pos += scnprintf(buf + pos, bufsz - pos,
1326			 "beacon_rssi_c:\t\t%u\t\t\t%u\n",
1327			 le32_to_cpu(general->beacon_rssi_c),
1328			 accum_general->beacon_rssi_c);
1329	pos += scnprintf(buf + pos, bufsz - pos,
1330			 "beacon_energy_a:\t%u\t\t\t%u\n",
1331			 le32_to_cpu(general->beacon_energy_a),
1332			 accum_general->beacon_energy_a);
1333	pos += scnprintf(buf + pos, bufsz - pos,
1334			 "beacon_energy_b:\t%u\t\t\t%u\n",
1335			 le32_to_cpu(general->beacon_energy_b),
1336			 accum_general->beacon_energy_b);
1337	pos += scnprintf(buf + pos, bufsz - pos,
1338			 "beacon_energy_c:\t%u\t\t\t%u\n",
1339			 le32_to_cpu(general->beacon_energy_c),
1340			 accum_general->beacon_energy_c);
1341
1342	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
1343	pos += scnprintf(buf + pos, bufsz - pos,
1344			"\t\t\tcurrent\t\t\taccumulative\n");
1345	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
1346			 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err);
1347	pos += scnprintf(buf + pos, bufsz - pos,
1348			 "overrun_err:\t\t%u\t\t\t%u\n",
1349			 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err);
1350	pos += scnprintf(buf + pos, bufsz - pos,
1351			 "early_overrun_err:\t%u\t\t\t%u\n",
1352			 le32_to_cpu(ht->early_overrun_err),
1353			 accum_ht->early_overrun_err);
1354	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
1355			 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good);
1356	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
1357			 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err);
1358	pos += scnprintf(buf + pos, bufsz - pos,
1359			 "mh_format_err:\t\t%u\t\t\t%u\n",
1360			 le32_to_cpu(ht->mh_format_err),
1361			 accum_ht->mh_format_err);
1362	pos += scnprintf(buf + pos, bufsz - pos,
1363			 "agg_crc32_good:\t\t%u\t\t\t%u\n",
1364			 le32_to_cpu(ht->agg_crc32_good),
1365			 accum_ht->agg_crc32_good);
1366	pos += scnprintf(buf + pos, bufsz - pos,
1367			 "agg_mpdu_cnt:\t\t%u\t\t\t%u\n",
1368			 le32_to_cpu(ht->agg_mpdu_cnt),
1369			 accum_ht->agg_mpdu_cnt);
1370	pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n",
1371			 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt);
1372
1373	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1374	kfree(buf);
1375	return ret;
1376}
1377
1378static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1379					char __user *user_buf,
1380					size_t count, loff_t *ppos)
1381{
1382	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1383	int pos = 0;
1384	char *buf;
1385	int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
1386	ssize_t ret;
1387	struct statistics_tx *tx, *accum_tx;
1388
1389	if (!iwl_is_alive(priv))
1390		return -EAGAIN;
1391
1392	/* make request to uCode to retrieve statistics information */
1393	mutex_lock(&priv->mutex);
1394	ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1395	mutex_unlock(&priv->mutex);
1396
1397	if (ret) {
1398		IWL_ERR(priv,
1399			"Error sending statistics request: %zd\n", ret);
1400		return -EAGAIN;
1401	}
1402	buf = kzalloc(bufsz, GFP_KERNEL);
1403	if (!buf) {
1404		IWL_ERR(priv, "Can not allocate Buffer\n");
1405		return -ENOMEM;
1406	}
1407
1408	/* the statistic information display here is based on
1409	 * the last statistics notification from uCode
1410	 * might not reflect the current uCode activity
1411	 */
1412	tx = &priv->statistics.tx;
1413	accum_tx = &priv->accum_statistics.tx;
1414	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1415	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
1416	pos += scnprintf(buf + pos, bufsz - pos,
1417			"\t\t\tcurrent\t\t\taccumulative\n");
1418	pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n",
1419			 le32_to_cpu(tx->preamble_cnt),
1420			 accum_tx->preamble_cnt);
1421	pos += scnprintf(buf + pos, bufsz - pos,
1422			 "rx_detected_cnt:\t\t%u\t\t\t%u\n",
1423			 le32_to_cpu(tx->rx_detected_cnt),
1424			 accum_tx->rx_detected_cnt);
1425	pos += scnprintf(buf + pos, bufsz - pos,
1426			 "bt_prio_defer_cnt:\t\t%u\t\t\t%u\n",
1427			 le32_to_cpu(tx->bt_prio_defer_cnt),
1428			 accum_tx->bt_prio_defer_cnt);
1429	pos += scnprintf(buf + pos, bufsz - pos,
1430			 "bt_prio_kill_cnt:\t\t%u\t\t\t%u\n",
1431			 le32_to_cpu(tx->bt_prio_kill_cnt),
1432			 accum_tx->bt_prio_kill_cnt);
1433	pos += scnprintf(buf + pos, bufsz - pos,
1434			 "few_bytes_cnt:\t\t\t%u\t\t\t%u\n",
1435			 le32_to_cpu(tx->few_bytes_cnt),
1436			 accum_tx->few_bytes_cnt);
1437	pos += scnprintf(buf + pos, bufsz - pos,
1438			 "cts_timeout:\t\t\t%u\t\t\t%u\n",
1439			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout);
1440	pos += scnprintf(buf + pos, bufsz - pos,
1441			 "ack_timeout:\t\t\t%u\t\t\t%u\n",
1442			 le32_to_cpu(tx->ack_timeout),
1443			 accum_tx->ack_timeout);
1444	pos += scnprintf(buf + pos, bufsz - pos,
1445			 "expected_ack_cnt:\t\t%u\t\t\t%u\n",
1446			 le32_to_cpu(tx->expected_ack_cnt),
1447			 accum_tx->expected_ack_cnt);
1448	pos += scnprintf(buf + pos, bufsz - pos,
1449			 "actual_ack_cnt:\t\t\t%u\t\t\t%u\n",
1450			 le32_to_cpu(tx->actual_ack_cnt),
1451			 accum_tx->actual_ack_cnt);
1452	pos += scnprintf(buf + pos, bufsz - pos,
1453			 "dump_msdu_cnt:\t\t\t%u\t\t\t%u\n",
1454			 le32_to_cpu(tx->dump_msdu_cnt),
1455			 accum_tx->dump_msdu_cnt);
1456	pos += scnprintf(buf + pos, bufsz - pos,
1457			 "abort_nxt_frame_mismatch:"
1458			 "\t%u\t\t\t%u\n",
1459			 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
1460			 accum_tx->burst_abort_next_frame_mismatch_cnt);
1461	pos += scnprintf(buf + pos, bufsz - pos,
1462			 "abort_missing_nxt_frame:"
1463			 "\t%u\t\t\t%u\n",
1464			 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
1465			 accum_tx->burst_abort_missing_next_frame_cnt);
1466	pos += scnprintf(buf + pos, bufsz - pos,
1467			 "cts_timeout_collision:\t\t%u\t\t\t%u\n",
1468			 le32_to_cpu(tx->cts_timeout_collision),
1469			 accum_tx->cts_timeout_collision);
1470	pos += scnprintf(buf + pos, bufsz - pos,
1471			"ack_ba_timeout_collision:\t%u\t\t\t%u\n",
1472			 le32_to_cpu(tx->ack_or_ba_timeout_collision),
1473			 accum_tx->ack_or_ba_timeout_collision);
1474	pos += scnprintf(buf + pos, bufsz - pos,
1475			 "agg ba_timeout:\t\t\t%u\t\t\t%u\n",
1476			 le32_to_cpu(tx->agg.ba_timeout),
1477			 accum_tx->agg.ba_timeout);
1478	pos += scnprintf(buf + pos, bufsz - pos,
1479			"agg ba_resched_frames:\t\t%u\t\t\t%u\n",
1480			 le32_to_cpu(tx->agg.ba_reschedule_frames),
1481			 accum_tx->agg.ba_reschedule_frames);
1482	pos += scnprintf(buf + pos, bufsz - pos,
1483			"agg scd_query_agg_frame:\t%u\t\t\t%u\n",
1484			 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
1485			 accum_tx->agg.scd_query_agg_frame_cnt);
1486	pos += scnprintf(buf + pos, bufsz - pos,
1487			 "agg scd_query_no_agg:\t\t%u\t\t\t%u\n",
1488			 le32_to_cpu(tx->agg.scd_query_no_agg),
1489			 accum_tx->agg.scd_query_no_agg);
1490	pos += scnprintf(buf + pos, bufsz - pos,
1491			 "agg scd_query_agg:\t\t%u\t\t\t%u\n",
1492			 le32_to_cpu(tx->agg.scd_query_agg),
1493			 accum_tx->agg.scd_query_agg);
1494	pos += scnprintf(buf + pos, bufsz - pos,
1495			"agg scd_query_mismatch:\t\t%u\t\t\t%u\n",
1496			 le32_to_cpu(tx->agg.scd_query_mismatch),
1497			 accum_tx->agg.scd_query_mismatch);
1498	pos += scnprintf(buf + pos, bufsz - pos,
1499			 "agg frame_not_ready:\t\t%u\t\t\t%u\n",
1500			 le32_to_cpu(tx->agg.frame_not_ready),
1501			 accum_tx->agg.frame_not_ready);
1502	pos += scnprintf(buf + pos, bufsz - pos,
1503			 "agg underrun:\t\t\t%u\t\t\t%u\n",
1504			 le32_to_cpu(tx->agg.underrun),
1505			 accum_tx->agg.underrun);
1506	pos += scnprintf(buf + pos, bufsz - pos,
1507			 "agg bt_prio_kill:\t\t%u\t\t\t%u\n",
1508			 le32_to_cpu(tx->agg.bt_prio_kill),
1509			 accum_tx->agg.bt_prio_kill);
1510	pos += scnprintf(buf + pos, bufsz - pos,
1511			 "agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n",
1512			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
1513			 accum_tx->agg.rx_ba_rsp_cnt);
1514
1515	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1516	kfree(buf);
1517	return ret;
1518}
1519
1520static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1521					char __user *user_buf,
1522					size_t count, loff_t *ppos)
1523{
1524	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1525	int pos = 0;
1526	char *buf;
1527	int bufsz = sizeof(struct statistics_general) * 4 + 250;
1528	ssize_t ret;
1529	struct statistics_general *general, *accum_general;
1530	struct statistics_dbg *dbg, *accum_dbg;
1531	struct statistics_div *div, *accum_div;
1532
1533	if (!iwl_is_alive(priv))
1534		return -EAGAIN;
1535
1536	/* make request to uCode to retrieve statistics information */
1537	mutex_lock(&priv->mutex);
1538	ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1539	mutex_unlock(&priv->mutex);
1540
1541	if (ret) {
1542		IWL_ERR(priv,
1543			"Error sending statistics request: %zd\n", ret);
1544		return -EAGAIN;
1545	}
1546	buf = kzalloc(bufsz, GFP_KERNEL);
1547	if (!buf) {
1548		IWL_ERR(priv, "Can not allocate Buffer\n");
1549		return -ENOMEM;
1550	}
1551
1552	/* the statistic information display here is based on
1553	 * the last statistics notification from uCode
1554	 * might not reflect the current uCode activity
1555	 */
1556	general = &priv->statistics.general;
1557	dbg = &priv->statistics.general.dbg;
1558	div = &priv->statistics.general.div;
1559	accum_general = &priv->accum_statistics.general;
1560	accum_dbg = &priv->accum_statistics.general.dbg;
1561	accum_div = &priv->accum_statistics.general.div;
1562	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1563	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
1564	pos += scnprintf(buf + pos, bufsz - pos,
1565			"\t\t\tcurrent\t\t\taccumulative\n");
1566	pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n",
1567			 le32_to_cpu(general->temperature));
1568	pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n",
1569			 le32_to_cpu(general->temperature_m));
1570	pos += scnprintf(buf + pos, bufsz - pos,
1571			 "burst_check:\t\t\t%u\t\t\t%u\n",
1572			 le32_to_cpu(dbg->burst_check),
1573			 accum_dbg->burst_check);
1574	pos += scnprintf(buf + pos, bufsz - pos,
1575			 "burst_count:\t\t\t%u\t\t\t%u\n",
1576			 le32_to_cpu(dbg->burst_count),
1577			 accum_dbg->burst_count);
1578	pos += scnprintf(buf + pos, bufsz - pos,
1579			 "sleep_time:\t\t\t%u\t\t\t%u\n",
1580			 le32_to_cpu(general->sleep_time),
1581			 accum_general->sleep_time);
1582	pos += scnprintf(buf + pos, bufsz - pos,
1583			 "slots_out:\t\t\t%u\t\t\t%u\n",
1584			 le32_to_cpu(general->slots_out),
1585			 accum_general->slots_out);
1586	pos += scnprintf(buf + pos, bufsz - pos,
1587			 "slots_idle:\t\t\t%u\t\t\t%u\n",
1588			 le32_to_cpu(general->slots_idle),
1589			 accum_general->slots_idle);
1590	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
1591			 le32_to_cpu(general->ttl_timestamp));
1592	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n",
1593			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a);
1594	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n",
1595			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b);
1596	pos += scnprintf(buf + pos, bufsz - pos,
1597			 "exec_time:\t\t\t%u\t\t\t%u\n",
1598			 le32_to_cpu(div->exec_time), accum_div->exec_time);
1599	pos += scnprintf(buf + pos, bufsz - pos,
1600			 "probe_time:\t\t\t%u\t\t\t%u\n",
1601			 le32_to_cpu(div->probe_time), accum_div->probe_time);
1602	pos += scnprintf(buf + pos, bufsz - pos,
1603			 "rx_enable_counter:\t\t%u\t\t\t%u\n",
1604			 le32_to_cpu(general->rx_enable_counter),
1605			 accum_general->rx_enable_counter);
1606	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1607	kfree(buf);
1608	return ret;
1609}
1610
1611static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
1612					char __user *user_buf,
1613					size_t count, loff_t *ppos) {
1614
1615	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1616	int pos = 0;
1617	int cnt = 0;
1618	char *buf;
1619	int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
1620	ssize_t ret;
1621	struct iwl_sensitivity_data *data;
1622
1623	data = &priv->sensitivity_data;
1624	buf = kzalloc(bufsz, GFP_KERNEL);
1625	if (!buf) {
1626		IWL_ERR(priv, "Can not allocate Buffer\n");
1627		return -ENOMEM;
1628	}
1629
1630	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
1631			data->auto_corr_ofdm);
1632	pos += scnprintf(buf + pos, bufsz - pos,
1633			"auto_corr_ofdm_mrc:\t\t %u\n",
1634			data->auto_corr_ofdm_mrc);
1635	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
1636			data->auto_corr_ofdm_x1);
1637	pos += scnprintf(buf + pos, bufsz - pos,
1638			"auto_corr_ofdm_mrc_x1:\t\t %u\n",
1639			data->auto_corr_ofdm_mrc_x1);
1640	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
1641			data->auto_corr_cck);
1642	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
1643			data->auto_corr_cck_mrc);
1644	pos += scnprintf(buf + pos, bufsz - pos,
1645			"last_bad_plcp_cnt_ofdm:\t\t %u\n",
1646			data->last_bad_plcp_cnt_ofdm);
1647	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
1648			data->last_fa_cnt_ofdm);
1649	pos += scnprintf(buf + pos, bufsz - pos,
1650			"last_bad_plcp_cnt_cck:\t\t %u\n",
1651			data->last_bad_plcp_cnt_cck);
1652	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
1653			data->last_fa_cnt_cck);
1654	pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
1655			data->nrg_curr_state);
1656	pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
1657			data->nrg_prev_state);
1658	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
1659	for (cnt = 0; cnt < 10; cnt++) {
1660		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1661				data->nrg_value[cnt]);
1662	}
1663	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1664	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
1665	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
1666		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1667				data->nrg_silence_rssi[cnt]);
1668	}
1669	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1670	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1671			data->nrg_silence_ref);
1672	pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1673			data->nrg_energy_idx);
1674	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1675			data->nrg_silence_idx);
1676	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1677			data->nrg_th_cck);
1678	pos += scnprintf(buf + pos, bufsz - pos,
1679			"nrg_auto_corr_silence_diff:\t %u\n",
1680			data->nrg_auto_corr_silence_diff);
1681	pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1682			data->num_in_cck_no_fa);
1683	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1684			data->nrg_th_ofdm);
1685
1686	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1687	kfree(buf);
1688	return ret;
1689}
1690
1691
1692static ssize_t iwl_dbgfs_chain_noise_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	int cnt = 0;
1699	char *buf;
1700	int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
1701	ssize_t ret;
1702	struct iwl_chain_noise_data *data;
1703
1704	data = &priv->chain_noise_data;
1705	buf = kzalloc(bufsz, GFP_KERNEL);
1706	if (!buf) {
1707		IWL_ERR(priv, "Can not allocate Buffer\n");
1708		return -ENOMEM;
1709	}
1710
1711	pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1712			data->active_chains);
1713	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1714			data->chain_noise_a);
1715	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1716			data->chain_noise_b);
1717	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1718			data->chain_noise_c);
1719	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1720			data->chain_signal_a);
1721	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1722			data->chain_signal_b);
1723	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1724			data->chain_signal_c);
1725	pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1726			data->beacon_count);
1727
1728	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1729	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1730		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1731				data->disconn_array[cnt]);
1732	}
1733	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1734	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1735	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1736		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1737				data->delta_gain_code[cnt]);
1738	}
1739	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1740	pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1741			data->radio_write);
1742	pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1743			data->state);
1744
1745	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1746	kfree(buf);
1747	return ret;
1748}
1749
1750static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
1751					char __user *user_buf,
1752					size_t count, loff_t *ppos) {
1753
1754	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1755	char buf[128];
1756	int pos = 0;
1757	ssize_t ret;
1758	const size_t bufsz = sizeof(buf);
1759	struct statistics_tx *tx;
1760
1761	if (!iwl_is_alive(priv))
1762		pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
1763	else {
1764		/* make request to uCode to retrieve statistics information */
1765		mutex_lock(&priv->mutex);
1766		ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1767		mutex_unlock(&priv->mutex);
1768
1769		if (ret) {
1770			IWL_ERR(priv, "Error sending statistics request: %zd\n",
1771				ret);
1772			return -EAGAIN;
1773		}
1774		tx = &priv->statistics.tx;
1775		if (tx->tx_power.ant_a ||
1776		    tx->tx_power.ant_b ||
1777		    tx->tx_power.ant_c) {
1778			pos += scnprintf(buf + pos, bufsz - pos,
1779				"tx power: (1/2 dB step)\n");
1780			if ((priv->cfg->valid_tx_ant & ANT_A) &&
1781			    tx->tx_power.ant_a)
1782				pos += scnprintf(buf + pos, bufsz - pos,
1783						"\tantenna A: 0x%X\n",
1784						tx->tx_power.ant_a);
1785			if ((priv->cfg->valid_tx_ant & ANT_B) &&
1786			    tx->tx_power.ant_b)
1787				pos += scnprintf(buf + pos, bufsz - pos,
1788						"\tantenna B: 0x%X\n",
1789						tx->tx_power.ant_b);
1790			if ((priv->cfg->valid_tx_ant & ANT_C) &&
1791			    tx->tx_power.ant_c)
1792				pos += scnprintf(buf + pos, bufsz - pos,
1793						"\tantenna C: 0x%X\n",
1794						tx->tx_power.ant_c);
1795		} else
1796			pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
1797	}
1798	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1799}
1800
1801static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
1802						    char __user *user_buf,
1803						    size_t count, loff_t *ppos)
1804{
1805	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1806	char buf[60];
1807	int pos = 0;
1808	const size_t bufsz = sizeof(buf);
1809	u32 pwrsave_status;
1810
1811	pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
1812			CSR_GP_REG_POWER_SAVE_STATUS_MSK;
1813
1814	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
1815	pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
1816		(pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1817		(pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1818		(pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1819		"error");
1820
1821	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1822}
1823
1824static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
1825					 const char __user *user_buf,
1826					 size_t count, loff_t *ppos)
1827{
1828	struct iwl_priv *priv = file->private_data;
1829	char buf[8];
1830	int buf_size;
1831	int clear;
1832
1833	memset(buf, 0, sizeof(buf));
1834	buf_size = min(count, sizeof(buf) -  1);
1835	if (copy_from_user(buf, user_buf, buf_size))
1836		return -EFAULT;
1837	if (sscanf(buf, "%d", &clear) != 1)
1838		return -EFAULT;
1839
1840	/* make request to uCode to retrieve statistics information */
1841	mutex_lock(&priv->mutex);
1842	iwl_send_statistics_request(priv, CMD_SYNC, true);
1843	mutex_unlock(&priv->mutex);
1844
1845	return count;
1846}
1847
1848static ssize_t iwl_dbgfs_csr_write(struct file *file,
1849					 const char __user *user_buf,
1850					 size_t count, loff_t *ppos)
1851{
1852	struct iwl_priv *priv = file->private_data;
1853	char buf[8];
1854	int buf_size;
1855	int csr;
1856
1857	memset(buf, 0, sizeof(buf));
1858	buf_size = min(count, sizeof(buf) -  1);
1859	if (copy_from_user(buf, user_buf, buf_size))
1860		return -EFAULT;
1861	if (sscanf(buf, "%d", &csr) != 1)
1862		return -EFAULT;
1863
1864	if (priv->cfg->ops->lib->dump_csr)
1865		priv->cfg->ops->lib->dump_csr(priv);
1866
1867	return count;
1868}
1869
1870static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
1871					char __user *user_buf,
1872					size_t count, loff_t *ppos) {
1873
1874	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1875	int pos = 0;
1876	char buf[128];
1877	const size_t bufsz = sizeof(buf);
1878	ssize_t ret;
1879
1880	pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
1881			priv->event_log.ucode_trace ? "On" : "Off");
1882	pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
1883			priv->event_log.non_wraps_count);
1884	pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
1885			priv->event_log.wraps_once_count);
1886	pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
1887			priv->event_log.wraps_more_count);
1888
1889	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1890	return ret;
1891}
1892
1893static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
1894					 const char __user *user_buf,
1895					 size_t count, loff_t *ppos)
1896{
1897	struct iwl_priv *priv = file->private_data;
1898	char buf[8];
1899	int buf_size;
1900	int trace;
1901
1902	memset(buf, 0, sizeof(buf));
1903	buf_size = min(count, sizeof(buf) -  1);
1904	if (copy_from_user(buf, user_buf, buf_size))
1905		return -EFAULT;
1906	if (sscanf(buf, "%d", &trace) != 1)
1907		return -EFAULT;
1908
1909	if (trace) {
1910		priv->event_log.ucode_trace = true;
1911		/* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
1912		mod_timer(&priv->ucode_trace,
1913			jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
1914	} else {
1915		priv->event_log.ucode_trace = false;
1916		del_timer_sync(&priv->ucode_trace);
1917	}
1918
1919	return count;
1920}
1921
1922DEBUGFS_READ_FILE_OPS(rx_statistics);
1923DEBUGFS_READ_FILE_OPS(tx_statistics);
1924DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1925DEBUGFS_READ_FILE_OPS(rx_queue);
1926DEBUGFS_READ_FILE_OPS(tx_queue);
1927DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1928DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1929DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1930DEBUGFS_READ_FILE_OPS(sensitivity);
1931DEBUGFS_READ_FILE_OPS(chain_noise);
1932DEBUGFS_READ_FILE_OPS(tx_power);
1933DEBUGFS_READ_FILE_OPS(power_save_status);
1934DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
1935DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
1936DEBUGFS_WRITE_FILE_OPS(csr);
1937DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
1938
1939/*
1940 * Create the debugfs files and directories
1941 *
1942 */
1943int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1944{
1945	struct iwl_debugfs *dbgfs;
1946	struct dentry *phyd = priv->hw->wiphy->debugfsdir;
1947	int ret = 0;
1948
1949	dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
1950	if (!dbgfs) {
1951		ret = -ENOMEM;
1952		goto err;
1953	}
1954
1955	priv->dbgfs = dbgfs;
1956	dbgfs->name = name;
1957	dbgfs->dir_drv = debugfs_create_dir(name, phyd);
1958	if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
1959		ret = -ENOENT;
1960		goto err;
1961	}
1962
1963	DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
1964	DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
1965	DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
1966	DEBUGFS_ADD_FILE(nvm, data, S_IRUSR);
1967	DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR);
1968	DEBUGFS_ADD_FILE(log_event, data, S_IWUSR);
1969	DEBUGFS_ADD_FILE(stations, data, S_IRUSR);
1970	DEBUGFS_ADD_FILE(channels, data, S_IRUSR);
1971	DEBUGFS_ADD_FILE(status, data, S_IRUSR);
1972	DEBUGFS_ADD_FILE(interrupt, data, S_IWUSR | S_IRUSR);
1973	DEBUGFS_ADD_FILE(qos, data, S_IRUSR);
1974	DEBUGFS_ADD_FILE(led, data, S_IRUSR);
1975	DEBUGFS_ADD_FILE(sleep_level_override, data, S_IWUSR | S_IRUSR);
1976	DEBUGFS_ADD_FILE(current_sleep_command, data, S_IRUSR);
1977	DEBUGFS_ADD_FILE(thermal_throttling, data, S_IRUSR);
1978	DEBUGFS_ADD_FILE(disable_ht40, data, S_IWUSR | S_IRUSR);
1979	DEBUGFS_ADD_FILE(rx_statistics, debug, S_IRUSR);
1980	DEBUGFS_ADD_FILE(tx_statistics, debug, S_IRUSR);
1981	DEBUGFS_ADD_FILE(traffic_log, debug, S_IWUSR | S_IRUSR);
1982	DEBUGFS_ADD_FILE(rx_queue, debug, S_IRUSR);
1983	DEBUGFS_ADD_FILE(tx_queue, debug, S_IRUSR);
1984	DEBUGFS_ADD_FILE(tx_power, debug, S_IRUSR);
1985	DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR);
1986	DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR);
1987	DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR);
1988	DEBUGFS_ADD_FILE(csr, debug, S_IWUSR);
1989	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1990		DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR);
1991		DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR);
1992		DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR);
1993		DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR);
1994		DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR);
1995		DEBUGFS_ADD_FILE(ucode_tracing, debug, S_IWUSR | S_IRUSR);
1996	}
1997	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
1998	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
1999			 &priv->disable_chain_noise_cal);
2000	if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
2001	    ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
2002		DEBUGFS_ADD_BOOL(disable_tx_power, rf,
2003				&priv->disable_tx_power_cal);
2004	return 0;
2005
2006err:
2007	IWL_ERR(priv, "Can't open the debugfs directory\n");
2008	iwl_dbgfs_unregister(priv);
2009	return ret;
2010}
2011EXPORT_SYMBOL(iwl_dbgfs_register);
2012
2013/**
2014 * Remove the debugfs files and directories
2015 *
2016 */
2017void iwl_dbgfs_unregister(struct iwl_priv *priv)
2018{
2019	if (!priv->dbgfs)
2020		return;
2021
2022	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
2023	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
2024	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
2025	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
2026	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
2027	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
2028	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
2029	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
2030	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
2031	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
2032	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
2033	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
2034	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
2035	DEBUGFS_REMOVE(priv->dbgfs->dir_data);
2036	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
2037	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
2038	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
2039	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
2040	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
2041	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
2042	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status);
2043	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2044			file_clear_ucode_statistics);
2045	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2046			file_clear_traffic_statistics);
2047	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr);
2048	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
2049		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2050			file_ucode_rx_stats);
2051		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2052			file_ucode_tx_stats);
2053		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2054			file_ucode_general_stats);
2055		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2056			file_sensitivity);
2057		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2058			file_chain_noise);
2059		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
2060			file_ucode_tracing);
2061	}
2062	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
2063	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
2064	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
2065	if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
2066	    ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
2067		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
2068	DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
2069	DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
2070	kfree(priv->dbgfs);
2071	priv->dbgfs = NULL;
2072}
2073EXPORT_SYMBOL(iwl_dbgfs_unregister);
2074
2075
2076
2077