iwl-debugfs.c revision 3ad3b92a5517c043ef30e4b95c4c39a35bbc36be
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) do {                             \
51	dbgfs->dbgfs_##parent##_files.file_##name =                     \
52	debugfs_create_file(#name, S_IWUSR | S_IRUSR,                   \
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 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
135	buf = kzalloc(bufsz, GFP_KERNEL);
136	if (!buf)
137		return -ENOMEM;
138	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
139	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
140		pos += scnprintf(buf + pos, bufsz - pos,
141				 "\t%s\t\t: %u\n",
142				 get_mgmt_string(cnt),
143				 priv->tx_stats.mgmt[cnt]);
144	}
145	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
146	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
147		pos += scnprintf(buf + pos, bufsz - pos,
148				 "\t%s\t\t: %u\n",
149				 get_ctrl_string(cnt),
150				 priv->tx_stats.ctrl[cnt]);
151	}
152	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
153	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
154			 priv->tx_stats.data_cnt);
155	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
156			 priv->tx_stats.data_bytes);
157	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
158	kfree(buf);
159	return ret;
160}
161
162static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file,
163					const char __user *user_buf,
164					size_t count, loff_t *ppos)
165{
166	struct iwl_priv *priv = file->private_data;
167	u32 clear_flag;
168	char buf[8];
169	int buf_size;
170
171	memset(buf, 0, sizeof(buf));
172	buf_size = min(count, sizeof(buf) -  1);
173	if (copy_from_user(buf, user_buf, buf_size))
174		return -EFAULT;
175	if (sscanf(buf, "%x", &clear_flag) != 1)
176		return -EFAULT;
177	if (clear_flag == 1)
178		iwl_clear_tx_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) * 24 * (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%s\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%s\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
223static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file,
224					const char __user *user_buf,
225					size_t count, loff_t *ppos)
226{
227	struct iwl_priv *priv = file->private_data;
228	u32 clear_flag;
229	char buf[8];
230	int buf_size;
231
232	memset(buf, 0, sizeof(buf));
233	buf_size = min(count, sizeof(buf) -  1);
234	if (copy_from_user(buf, user_buf, buf_size))
235		return -EFAULT;
236	if (sscanf(buf, "%x", &clear_flag) != 1)
237		return -EFAULT;
238	if (clear_flag == 1)
239		iwl_clear_rx_stats(priv);
240	return count;
241}
242
243#define BYTE1_MASK 0x000000ff;
244#define BYTE2_MASK 0x0000ffff;
245#define BYTE3_MASK 0x00ffffff;
246static ssize_t iwl_dbgfs_sram_read(struct file *file,
247					char __user *user_buf,
248					size_t count, loff_t *ppos)
249{
250	u32 val;
251	char buf[1024];
252	ssize_t ret;
253	int i;
254	int pos = 0;
255	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
256	const size_t bufsz = sizeof(buf);
257
258	for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
259		val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
260					priv->dbgfs->sram_len - i);
261		if (i < 4) {
262			switch (i) {
263			case 1:
264				val &= BYTE1_MASK;
265				break;
266			case 2:
267				val &= BYTE2_MASK;
268				break;
269			case 3:
270				val &= BYTE3_MASK;
271				break;
272			}
273		}
274		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
275	}
276	pos += scnprintf(buf + pos, bufsz - pos, "\n");
277
278	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
279	return ret;
280}
281
282static ssize_t iwl_dbgfs_sram_write(struct file *file,
283					const char __user *user_buf,
284					size_t count, loff_t *ppos)
285{
286	struct iwl_priv *priv = file->private_data;
287	char buf[64];
288	int buf_size;
289	u32 offset, len;
290
291	memset(buf, 0, sizeof(buf));
292	buf_size = min(count, sizeof(buf) -  1);
293	if (copy_from_user(buf, user_buf, buf_size))
294		return -EFAULT;
295
296	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
297		priv->dbgfs->sram_offset = offset;
298		priv->dbgfs->sram_len = len;
299	} else {
300		priv->dbgfs->sram_offset = 0;
301		priv->dbgfs->sram_len = 0;
302	}
303
304	return count;
305}
306
307static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
308					size_t count, loff_t *ppos)
309{
310	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
311	struct iwl_station_entry *station;
312	int max_sta = priv->hw_params.max_stations;
313	char *buf;
314	int i, j, pos = 0;
315	ssize_t ret;
316	/* Add 30 for initial string */
317	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
318
319	buf = kmalloc(bufsz, GFP_KERNEL);
320	if (!buf)
321		return -ENOMEM;
322
323	pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
324			priv->num_stations);
325
326	for (i = 0; i < max_sta; i++) {
327		station = &priv->stations[i];
328		if (station->used) {
329			pos += scnprintf(buf + pos, bufsz - pos,
330					"station %d:\ngeneral data:\n", i+1);
331			pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
332					station->sta.sta.sta_id);
333			pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
334					station->sta.mode);
335			pos += scnprintf(buf + pos, bufsz - pos,
336					"flags: 0x%x\n",
337					station->sta.station_flags_msk);
338			pos += scnprintf(buf + pos, bufsz - pos,
339					"ps_status: %u\n", station->ps_status);
340			pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
341			pos += scnprintf(buf + pos, bufsz - pos,
342					"seq_num\t\ttxq_id");
343			pos += scnprintf(buf + pos, bufsz - pos,
344					"\tframe_count\twait_for_ba\t");
345			pos += scnprintf(buf + pos, bufsz - pos,
346					"start_idx\tbitmap0\t");
347			pos += scnprintf(buf + pos, bufsz - pos,
348					"bitmap1\trate_n_flags");
349			pos += scnprintf(buf + pos, bufsz - pos, "\n");
350
351			for (j = 0; j < MAX_TID_COUNT; j++) {
352				pos += scnprintf(buf + pos, bufsz - pos,
353						"[%d]:\t\t%u", j,
354						station->tid[j].seq_number);
355				pos += scnprintf(buf + pos, bufsz - pos,
356						"\t%u\t\t%u\t\t%u\t\t",
357						station->tid[j].agg.txq_id,
358						station->tid[j].agg.frame_count,
359						station->tid[j].agg.wait_for_ba);
360				pos += scnprintf(buf + pos, bufsz - pos,
361						"%u\t%llu\t%u",
362						station->tid[j].agg.start_idx,
363						(unsigned long long)station->tid[j].agg.bitmap,
364						station->tid[j].agg.rate_n_flags);
365				pos += scnprintf(buf + pos, bufsz - pos, "\n");
366			}
367			pos += scnprintf(buf + pos, bufsz - pos, "\n");
368		}
369	}
370
371	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
372	kfree(buf);
373	return ret;
374}
375
376static ssize_t iwl_dbgfs_nvm_read(struct file *file,
377				       char __user *user_buf,
378				       size_t count,
379				       loff_t *ppos)
380{
381	ssize_t ret;
382	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
383	int pos = 0, ofs = 0, buf_size = 0;
384	const u8 *ptr;
385	char *buf;
386	size_t eeprom_len = priv->cfg->eeprom_size;
387	buf_size = 4 * eeprom_len + 256;
388
389	if (eeprom_len % 16) {
390		IWL_ERR(priv, "NVM size is not multiple of 16.\n");
391		return -ENODATA;
392	}
393
394	ptr = priv->eeprom;
395	if (!ptr) {
396		IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
397		return -ENOMEM;
398	}
399
400	/* 4 characters for byte 0xYY */
401	buf = kzalloc(buf_size, GFP_KERNEL);
402	if (!buf) {
403		IWL_ERR(priv, "Can not allocate Buffer\n");
404		return -ENOMEM;
405	}
406	pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
407			(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
408			? "OTP" : "EEPROM");
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);
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		iwl_dump_nic_event_log(priv);
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_INIT:\t\t %d\n",
536		test_bit(STATUS_INIT, &priv->status));
537	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
538		test_bit(STATUS_ALIVE, &priv->status));
539	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
540		test_bit(STATUS_READY, &priv->status));
541	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
542		test_bit(STATUS_TEMPERATURE, &priv->status));
543	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
544		test_bit(STATUS_GEO_CONFIGURED, &priv->status));
545	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
546		test_bit(STATUS_EXIT_PENDING, &priv->status));
547	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
548		test_bit(STATUS_STATISTICS, &priv->status));
549	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
550		test_bit(STATUS_SCANNING, &priv->status));
551	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
552		test_bit(STATUS_SCAN_ABORTING, &priv->status));
553	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
554		test_bit(STATUS_SCAN_HW, &priv->status));
555	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
556		test_bit(STATUS_POWER_PMI, &priv->status));
557	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
558		test_bit(STATUS_FW_ERROR, &priv->status));
559	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n",
560		test_bit(STATUS_MODE_PENDING, &priv->status));
561	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
562}
563
564static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
565					char __user *user_buf,
566					size_t count, loff_t *ppos) {
567
568	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
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	pos += scnprintf(buf + pos, bufsz - pos,
582			"Interrupt Statistics Report:\n");
583
584	pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
585		priv->isr_stats.hw);
586	pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
587		priv->isr_stats.sw);
588	if (priv->isr_stats.sw > 0) {
589		pos += scnprintf(buf + pos, bufsz - pos,
590			"\tLast Restarting Code:  0x%X\n",
591			priv->isr_stats.sw_err);
592	}
593#ifdef CONFIG_IWLWIFI_DEBUG
594	pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
595		priv->isr_stats.sch);
596	pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
597		priv->isr_stats.alive);
598#endif
599	pos += scnprintf(buf + pos, bufsz - pos,
600		"HW RF KILL switch toggled:\t %u\n",
601		priv->isr_stats.rfkill);
602
603	pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
604		priv->isr_stats.ctkill);
605
606	pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
607		priv->isr_stats.wakeup);
608
609	pos += scnprintf(buf + pos, bufsz - pos,
610		"Rx command responses:\t\t %u\n",
611		priv->isr_stats.rx);
612	for (cnt = 0; cnt < REPLY_MAX; cnt++) {
613		if (priv->isr_stats.rx_handlers[cnt] > 0)
614			pos += scnprintf(buf + pos, bufsz - pos,
615				"\tRx handler[%36s]:\t\t %u\n",
616				get_cmd_string(cnt),
617				priv->isr_stats.rx_handlers[cnt]);
618	}
619
620	pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
621		priv->isr_stats.tx);
622
623	pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
624		priv->isr_stats.unhandled);
625
626	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
627	kfree(buf);
628	return ret;
629}
630
631static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
632					 const char __user *user_buf,
633					 size_t count, loff_t *ppos)
634{
635	struct iwl_priv *priv = file->private_data;
636	char buf[8];
637	int buf_size;
638	u32 reset_flag;
639
640	memset(buf, 0, sizeof(buf));
641	buf_size = min(count, sizeof(buf) -  1);
642	if (copy_from_user(buf, user_buf, buf_size))
643		return -EFAULT;
644	if (sscanf(buf, "%x", &reset_flag) != 1)
645		return -EFAULT;
646	if (reset_flag == 0)
647		iwl_clear_isr_stats(priv);
648
649	return count;
650}
651
652static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
653				       size_t count, loff_t *ppos)
654{
655	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
656	int pos = 0, i;
657	char buf[256];
658	const size_t bufsz = sizeof(buf);
659	ssize_t ret;
660
661	for (i = 0; i < AC_NUM; i++) {
662		pos += scnprintf(buf + pos, bufsz - pos,
663			"\tcw_min\tcw_max\taifsn\ttxop\n");
664		pos += scnprintf(buf + pos, bufsz - pos,
665				"AC[%d]\t%u\t%u\t%u\t%u\n", i,
666				priv->qos_data.def_qos_parm.ac[i].cw_min,
667				priv->qos_data.def_qos_parm.ac[i].cw_max,
668				priv->qos_data.def_qos_parm.ac[i].aifsn,
669				priv->qos_data.def_qos_parm.ac[i].edca_txop);
670	}
671	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
672	return ret;
673}
674
675#ifdef CONFIG_IWLWIFI_LEDS
676static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
677				  size_t count, loff_t *ppos)
678{
679	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
680	int pos = 0;
681	char buf[256];
682	const size_t bufsz = sizeof(buf);
683	ssize_t ret;
684
685	pos += scnprintf(buf + pos, bufsz - pos,
686			 "allow blinking: %s\n",
687			 (priv->allow_blinking) ? "True" : "False");
688	if (priv->allow_blinking) {
689		pos += scnprintf(buf + pos, bufsz - pos,
690				 "Led blinking rate: %u\n",
691				 priv->last_blink_rate);
692		pos += scnprintf(buf + pos, bufsz - pos,
693				 "Last blink time: %lu\n",
694				 priv->last_blink_time);
695	}
696
697	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
698	return ret;
699}
700#endif
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
779DEBUGFS_READ_WRITE_FILE_OPS(sram);
780DEBUGFS_WRITE_FILE_OPS(log_event);
781DEBUGFS_READ_FILE_OPS(nvm);
782DEBUGFS_READ_FILE_OPS(stations);
783DEBUGFS_READ_FILE_OPS(channels);
784DEBUGFS_READ_FILE_OPS(status);
785DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
786DEBUGFS_READ_FILE_OPS(qos);
787#ifdef CONFIG_IWLWIFI_LEDS
788DEBUGFS_READ_FILE_OPS(led);
789#endif
790DEBUGFS_READ_FILE_OPS(thermal_throttling);
791DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
792
793static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
794					 char __user *user_buf,
795					 size_t count, loff_t *ppos)
796{
797	struct iwl_priv *priv = file->private_data;
798	int pos = 0, ofs = 0;
799	int cnt = 0, entry;
800	struct iwl_tx_queue *txq;
801	struct iwl_queue *q;
802	struct iwl_rx_queue *rxq = &priv->rxq;
803	char *buf;
804	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
805		(IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
806	const u8 *ptr;
807	ssize_t ret;
808
809	buf = kzalloc(bufsz, GFP_KERNEL);
810	if (!buf) {
811		IWL_ERR(priv, "Can not allocate buffer\n");
812		return -ENOMEM;
813	}
814	pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
815	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
816		txq = &priv->txq[cnt];
817		q = &txq->q;
818		pos += scnprintf(buf + pos, bufsz - pos,
819				"q[%d]: read_ptr: %u, write_ptr: %u\n",
820				cnt, q->read_ptr, q->write_ptr);
821	}
822	if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
823		ptr = priv->tx_traffic;
824		pos += scnprintf(buf + pos, bufsz - pos,
825				"Tx Traffic idx: %u\n",	priv->tx_traffic_idx);
826		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
827			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
828			     entry++,  ofs += 16) {
829				pos += scnprintf(buf + pos, bufsz - pos,
830						"0x%.4x ", ofs);
831				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
832						   buf + pos, bufsz - pos, 0);
833				pos += strlen(buf);
834				if (bufsz - pos > 0)
835					buf[pos++] = '\n';
836			}
837		}
838	}
839
840	pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
841	pos += scnprintf(buf + pos, bufsz - pos,
842			"read: %u, write: %u\n",
843			 rxq->read, rxq->write);
844
845	if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
846		ptr = priv->rx_traffic;
847		pos += scnprintf(buf + pos, bufsz - pos,
848				"Rx Traffic idx: %u\n",	priv->rx_traffic_idx);
849		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
850			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
851			     entry++,  ofs += 16) {
852				pos += scnprintf(buf + pos, bufsz - pos,
853						"0x%.4x ", ofs);
854				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
855						   buf + pos, bufsz - pos, 0);
856				pos += strlen(buf);
857				if (bufsz - pos > 0)
858					buf[pos++] = '\n';
859			}
860		}
861	}
862
863	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
864	kfree(buf);
865	return ret;
866}
867
868static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
869					 const char __user *user_buf,
870					 size_t count, loff_t *ppos)
871{
872	struct iwl_priv *priv = file->private_data;
873	char buf[8];
874	int buf_size;
875	int traffic_log;
876
877	memset(buf, 0, sizeof(buf));
878	buf_size = min(count, sizeof(buf) -  1);
879	if (copy_from_user(buf, user_buf, buf_size))
880		return -EFAULT;
881	if (sscanf(buf, "%d", &traffic_log) != 1)
882		return -EFAULT;
883	if (traffic_log == 0)
884		iwl_reset_traffic_log(priv);
885
886	return count;
887}
888
889static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
890						char __user *user_buf,
891						size_t count, loff_t *ppos) {
892
893	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
894	struct iwl_tx_queue *txq;
895	struct iwl_queue *q;
896	char *buf;
897	int pos = 0;
898	int cnt;
899	int ret;
900	const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
901
902	buf = kzalloc(bufsz, GFP_KERNEL);
903	if (!buf)
904		return -ENOMEM;
905
906	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
907		txq = &priv->txq[cnt];
908		q = &txq->q;
909		pos += scnprintf(buf + pos, bufsz - pos,
910				"hwq %.2d: read=%u write=%u stop=%d"
911				" swq_id=%#.2x (ac %d/hwq %d)\n",
912				cnt, q->read_ptr, q->write_ptr,
913				!!test_bit(cnt, priv->queue_stopped),
914				txq->swq_id,
915				txq->swq_id & 0x80 ? txq->swq_id & 3 :
916				txq->swq_id,
917				txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
918				0x1f : txq->swq_id);
919		if (cnt >= 4)
920			continue;
921		/* for the ACs, display the stop count too */
922		pos += scnprintf(buf + pos, bufsz - pos,
923				"        stop-count: %d\n",
924				atomic_read(&priv->queue_stop_count[cnt]));
925	}
926	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
927	kfree(buf);
928	return ret;
929}
930
931static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
932						char __user *user_buf,
933						size_t count, loff_t *ppos) {
934
935	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
936	struct iwl_rx_queue *rxq = &priv->rxq;
937	char buf[256];
938	int pos = 0;
939	const size_t bufsz = sizeof(buf);
940
941	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
942						rxq->read);
943	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
944						rxq->write);
945	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
946						rxq->free_count);
947	pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
948			 le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
949	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
950}
951
952#define UCODE_STATISTICS_CLEAR_MSK		(0x1 << 0)
953#define UCODE_STATISTICS_FREQUENCY_MSK		(0x1 << 1)
954#define UCODE_STATISTICS_NARROW_BAND_MSK	(0x1 << 2)
955
956static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
957				     int bufsz)
958{
959	int p = 0;
960
961	p += scnprintf(buf + p, bufsz - p,
962		"Statistics Flag(0x%X):\n",
963		le32_to_cpu(priv->statistics.flag));
964	if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
965		p += scnprintf(buf + p, bufsz - p,
966		"\tStatistics have been cleared\n");
967	p += scnprintf(buf + p, bufsz - p,
968		"\tOperational Frequency: %s\n",
969		(le32_to_cpu(priv->statistics.flag) &
970		UCODE_STATISTICS_FREQUENCY_MSK)
971		 ? "2.4 GHz" : "5.2 GHz");
972	p += scnprintf(buf + p, bufsz - p,
973		"\tTGj Narrow Band: %s\n",
974		(le32_to_cpu(priv->statistics.flag) &
975		UCODE_STATISTICS_NARROW_BAND_MSK)
976		 ? "enabled" : "disabled");
977	return p;
978}
979
980
981static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
982					char __user *user_buf,
983					size_t count, loff_t *ppos)
984{
985	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
986	int pos = 0;
987	char *buf;
988	int bufsz = sizeof(struct statistics_rx_phy) * 20 +
989		sizeof(struct statistics_rx_non_phy) * 20 +
990		sizeof(struct statistics_rx_ht_phy) * 20 + 400;
991	ssize_t ret;
992	struct statistics_rx_phy *ofdm;
993	struct statistics_rx_phy *cck;
994	struct statistics_rx_non_phy *general;
995	struct statistics_rx_ht_phy *ht;
996
997	if (!iwl_is_alive(priv))
998		return -EAGAIN;
999
1000	/* make request to uCode to retrieve statistics information */
1001	mutex_lock(&priv->mutex);
1002	ret = iwl_send_statistics_request(priv, 0);
1003	mutex_unlock(&priv->mutex);
1004
1005	if (ret) {
1006		IWL_ERR(priv,
1007			"Error sending statistics request: %zd\n", ret);
1008		return -EAGAIN;
1009	}
1010	buf = kzalloc(bufsz, GFP_KERNEL);
1011	if (!buf) {
1012		IWL_ERR(priv, "Can not allocate Buffer\n");
1013		return -ENOMEM;
1014	}
1015
1016	/* the statistic information display here is based on
1017	 * the last statistics notification from uCode
1018	 * might not reflect the current uCode activity
1019	 */
1020	ofdm = &priv->statistics.rx.ofdm;
1021	cck = &priv->statistics.rx.cck;
1022	general = &priv->statistics.rx.general;
1023	ht = &priv->statistics.rx.ofdm_ht;
1024	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1025	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
1026	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1027			 le32_to_cpu(ofdm->ina_cnt));
1028	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1029			 le32_to_cpu(ofdm->fina_cnt));
1030	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1031			 le32_to_cpu(ofdm->plcp_err));
1032	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1033			 le32_to_cpu(ofdm->crc32_err));
1034	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1035			 le32_to_cpu(ofdm->overrun_err));
1036	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1037			 le32_to_cpu(ofdm->early_overrun_err));
1038	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1039			 le32_to_cpu(ofdm->crc32_good));
1040	pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1041			 le32_to_cpu(ofdm->false_alarm_cnt));
1042	pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1043			 le32_to_cpu(ofdm->fina_sync_err_cnt));
1044	pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1045			 le32_to_cpu(ofdm->sfd_timeout));
1046	pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1047			 le32_to_cpu(ofdm->fina_timeout));
1048	pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1049			 le32_to_cpu(ofdm->unresponded_rts));
1050	pos += scnprintf(buf + pos, bufsz - pos,
1051			"rxe_frame_limit_overrun: %u\n",
1052			le32_to_cpu(ofdm->rxe_frame_limit_overrun));
1053	pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1054			 le32_to_cpu(ofdm->sent_ack_cnt));
1055	pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1056			 le32_to_cpu(ofdm->sent_cts_cnt));
1057	pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1058			 le32_to_cpu(ofdm->sent_ba_rsp_cnt));
1059	pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1060			 le32_to_cpu(ofdm->dsp_self_kill));
1061	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1062			 le32_to_cpu(ofdm->mh_format_err));
1063	pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1064			 le32_to_cpu(ofdm->re_acq_main_rssi_sum));
1065
1066	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
1067	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1068			 le32_to_cpu(cck->ina_cnt));
1069	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1070			 le32_to_cpu(cck->fina_cnt));
1071	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1072			 le32_to_cpu(cck->plcp_err));
1073	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1074			 le32_to_cpu(cck->crc32_err));
1075	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1076			 le32_to_cpu(cck->overrun_err));
1077	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1078			 le32_to_cpu(cck->early_overrun_err));
1079	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1080			 le32_to_cpu(cck->crc32_good));
1081	pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1082			 le32_to_cpu(cck->false_alarm_cnt));
1083	pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1084			 le32_to_cpu(cck->fina_sync_err_cnt));
1085	pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1086			 le32_to_cpu(cck->sfd_timeout));
1087	pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1088			 le32_to_cpu(cck->fina_timeout));
1089	pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1090			 le32_to_cpu(cck->unresponded_rts));
1091	pos += scnprintf(buf + pos, bufsz - pos,
1092			"rxe_frame_limit_overrun: %u\n",
1093			le32_to_cpu(cck->rxe_frame_limit_overrun));
1094	pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1095			 le32_to_cpu(cck->sent_ack_cnt));
1096	pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1097			 le32_to_cpu(cck->sent_cts_cnt));
1098	pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1099			 le32_to_cpu(cck->sent_ba_rsp_cnt));
1100	pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1101			 le32_to_cpu(cck->dsp_self_kill));
1102	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1103			 le32_to_cpu(cck->mh_format_err));
1104	pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1105			 le32_to_cpu(cck->re_acq_main_rssi_sum));
1106
1107	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
1108	pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
1109			 le32_to_cpu(general->bogus_cts));
1110	pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
1111			 le32_to_cpu(general->bogus_ack));
1112	pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
1113			 le32_to_cpu(general->non_bssid_frames));
1114	pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
1115			 le32_to_cpu(general->filtered_frames));
1116	pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
1117			 le32_to_cpu(general->non_channel_beacons));
1118	pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
1119			 le32_to_cpu(general->channel_beacons));
1120	pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
1121			 le32_to_cpu(general->num_missed_bcon));
1122	pos += scnprintf(buf + pos, bufsz - pos,
1123			"adc_rx_saturation_time: %u\n",
1124			le32_to_cpu(general->adc_rx_saturation_time));
1125	pos += scnprintf(buf + pos, bufsz - pos,
1126			"ina_detection_search_time: %u\n",
1127			le32_to_cpu(general->ina_detection_search_time));
1128	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
1129			 le32_to_cpu(general->beacon_silence_rssi_a));
1130	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
1131			 le32_to_cpu(general->beacon_silence_rssi_b));
1132	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
1133			 le32_to_cpu(general->beacon_silence_rssi_c));
1134	pos += scnprintf(buf + pos, bufsz - pos,
1135			"interference_data_flag: %u\n",
1136			le32_to_cpu(general->interference_data_flag));
1137	pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
1138			 le32_to_cpu(general->channel_load));
1139	pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
1140			 le32_to_cpu(general->dsp_false_alarms));
1141	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
1142			 le32_to_cpu(general->beacon_rssi_a));
1143	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
1144			 le32_to_cpu(general->beacon_rssi_b));
1145	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
1146			 le32_to_cpu(general->beacon_rssi_c));
1147	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
1148			 le32_to_cpu(general->beacon_energy_a));
1149	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
1150			 le32_to_cpu(general->beacon_energy_b));
1151	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
1152			 le32_to_cpu(general->beacon_energy_c));
1153
1154	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
1155	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1156			 le32_to_cpu(ht->plcp_err));
1157	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1158			 le32_to_cpu(ht->overrun_err));
1159	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1160			 le32_to_cpu(ht->early_overrun_err));
1161	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1162			 le32_to_cpu(ht->crc32_good));
1163	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1164			 le32_to_cpu(ht->crc32_err));
1165	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1166			 le32_to_cpu(ht->mh_format_err));
1167	pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
1168			 le32_to_cpu(ht->agg_crc32_good));
1169	pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
1170			 le32_to_cpu(ht->agg_mpdu_cnt));
1171	pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
1172			 le32_to_cpu(ht->agg_cnt));
1173
1174	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1175	kfree(buf);
1176	return ret;
1177}
1178
1179static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1180					char __user *user_buf,
1181					size_t count, loff_t *ppos)
1182{
1183	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1184	int pos = 0;
1185	char *buf;
1186	int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
1187	ssize_t ret;
1188	struct statistics_tx *tx;
1189
1190	if (!iwl_is_alive(priv))
1191		return -EAGAIN;
1192
1193	/* make request to uCode to retrieve statistics information */
1194	mutex_lock(&priv->mutex);
1195	ret = iwl_send_statistics_request(priv, 0);
1196	mutex_unlock(&priv->mutex);
1197
1198	if (ret) {
1199		IWL_ERR(priv,
1200			"Error sending statistics request: %zd\n", ret);
1201		return -EAGAIN;
1202	}
1203	buf = kzalloc(bufsz, GFP_KERNEL);
1204	if (!buf) {
1205		IWL_ERR(priv, "Can not allocate Buffer\n");
1206		return -ENOMEM;
1207	}
1208
1209	/* the statistic information display here is based on
1210	 * the last statistics notification from uCode
1211	 * might not reflect the current uCode activity
1212	 */
1213	tx = &priv->statistics.tx;
1214	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1215	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
1216	pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
1217			 le32_to_cpu(tx->preamble_cnt));
1218	pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
1219			 le32_to_cpu(tx->rx_detected_cnt));
1220	pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
1221			 le32_to_cpu(tx->bt_prio_defer_cnt));
1222	pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
1223			 le32_to_cpu(tx->bt_prio_kill_cnt));
1224	pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
1225			 le32_to_cpu(tx->few_bytes_cnt));
1226	pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
1227			 le32_to_cpu(tx->cts_timeout));
1228	pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
1229			 le32_to_cpu(tx->ack_timeout));
1230	pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
1231			 le32_to_cpu(tx->expected_ack_cnt));
1232	pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
1233			 le32_to_cpu(tx->actual_ack_cnt));
1234	pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
1235			 le32_to_cpu(tx->dump_msdu_cnt));
1236	pos += scnprintf(buf + pos, bufsz - pos,
1237			"burst_abort_next_frame_mismatch_cnt: %u\n",
1238			le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
1239	pos += scnprintf(buf + pos, bufsz - pos,
1240			"burst_abort_missing_next_frame_cnt: %u\n",
1241			le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
1242	pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
1243			 le32_to_cpu(tx->cts_timeout_collision));
1244	pos += scnprintf(buf + pos, bufsz - pos,
1245			"ack_or_ba_timeout_collision: %u\n",
1246			le32_to_cpu(tx->ack_or_ba_timeout_collision));
1247	pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
1248			 le32_to_cpu(tx->agg.ba_timeout));
1249	pos += scnprintf(buf + pos, bufsz - pos,
1250			"agg ba_reschedule_frames: %u\n",
1251			le32_to_cpu(tx->agg.ba_reschedule_frames));
1252	pos += scnprintf(buf + pos, bufsz - pos,
1253			"agg scd_query_agg_frame_cnt: %u\n",
1254			le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
1255	pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
1256			 le32_to_cpu(tx->agg.scd_query_no_agg));
1257	pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
1258			 le32_to_cpu(tx->agg.scd_query_agg));
1259	pos += scnprintf(buf + pos, bufsz - pos,
1260			"agg scd_query_mismatch: %u\n",
1261			le32_to_cpu(tx->agg.scd_query_mismatch));
1262	pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
1263			 le32_to_cpu(tx->agg.frame_not_ready));
1264	pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
1265			 le32_to_cpu(tx->agg.underrun));
1266	pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
1267			 le32_to_cpu(tx->agg.bt_prio_kill));
1268	pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
1269			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
1270
1271	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1272	kfree(buf);
1273	return ret;
1274}
1275
1276static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1277					char __user *user_buf,
1278					size_t count, loff_t *ppos)
1279{
1280	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1281	int pos = 0;
1282	char *buf;
1283	int bufsz = sizeof(struct statistics_general) * 4 + 250;
1284	ssize_t ret;
1285	struct statistics_general *general;
1286	struct statistics_dbg *dbg;
1287	struct statistics_div *div;
1288
1289	if (!iwl_is_alive(priv))
1290		return -EAGAIN;
1291
1292	/* make request to uCode to retrieve statistics information */
1293	mutex_lock(&priv->mutex);
1294	ret = iwl_send_statistics_request(priv, 0);
1295	mutex_unlock(&priv->mutex);
1296
1297	if (ret) {
1298		IWL_ERR(priv,
1299			"Error sending statistics request: %zd\n", ret);
1300		return -EAGAIN;
1301	}
1302	buf = kzalloc(bufsz, GFP_KERNEL);
1303	if (!buf) {
1304		IWL_ERR(priv, "Can not allocate Buffer\n");
1305		return -ENOMEM;
1306	}
1307
1308	/* the statistic information display here is based on
1309	 * the last statistics notification from uCode
1310	 * might not reflect the current uCode activity
1311	 */
1312	general = &priv->statistics.general;
1313	dbg = &priv->statistics.general.dbg;
1314	div = &priv->statistics.general.div;
1315	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1316	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
1317	pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
1318			 le32_to_cpu(general->temperature));
1319	pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
1320			 le32_to_cpu(general->temperature_m));
1321	pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
1322			 le32_to_cpu(dbg->burst_check));
1323	pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
1324			 le32_to_cpu(dbg->burst_count));
1325	pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
1326			 le32_to_cpu(general->sleep_time));
1327	pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
1328			 le32_to_cpu(general->slots_out));
1329	pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
1330			 le32_to_cpu(general->slots_idle));
1331	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
1332			 le32_to_cpu(general->ttl_timestamp));
1333	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
1334			 le32_to_cpu(div->tx_on_a));
1335	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
1336			 le32_to_cpu(div->tx_on_b));
1337	pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
1338			 le32_to_cpu(div->exec_time));
1339	pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
1340			 le32_to_cpu(div->probe_time));
1341	pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
1342			 le32_to_cpu(general->rx_enable_counter));
1343	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1344	kfree(buf);
1345	return ret;
1346}
1347
1348static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
1349					char __user *user_buf,
1350					size_t count, loff_t *ppos) {
1351
1352	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1353	int pos = 0;
1354	int cnt = 0;
1355	char *buf;
1356	int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
1357	ssize_t ret;
1358	struct iwl_sensitivity_data *data;
1359
1360	data = &priv->sensitivity_data;
1361	buf = kzalloc(bufsz, GFP_KERNEL);
1362	if (!buf) {
1363		IWL_ERR(priv, "Can not allocate Buffer\n");
1364		return -ENOMEM;
1365	}
1366
1367	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
1368			data->auto_corr_ofdm);
1369	pos += scnprintf(buf + pos, bufsz - pos,
1370			"auto_corr_ofdm_mrc:\t\t %u\n",
1371			data->auto_corr_ofdm_mrc);
1372	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
1373			data->auto_corr_ofdm_x1);
1374	pos += scnprintf(buf + pos, bufsz - pos,
1375			"auto_corr_ofdm_mrc_x1:\t\t %u\n",
1376			data->auto_corr_ofdm_mrc_x1);
1377	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
1378			data->auto_corr_cck);
1379	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
1380			data->auto_corr_cck_mrc);
1381	pos += scnprintf(buf + pos, bufsz - pos,
1382			"last_bad_plcp_cnt_ofdm:\t\t %u\n",
1383			data->last_bad_plcp_cnt_ofdm);
1384	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
1385			data->last_fa_cnt_ofdm);
1386	pos += scnprintf(buf + pos, bufsz - pos,
1387			"last_bad_plcp_cnt_cck:\t\t %u\n",
1388			data->last_bad_plcp_cnt_cck);
1389	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
1390			data->last_fa_cnt_cck);
1391	pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
1392			data->nrg_curr_state);
1393	pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
1394			data->nrg_prev_state);
1395	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
1396	for (cnt = 0; cnt < 10; cnt++) {
1397		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1398				data->nrg_value[cnt]);
1399	}
1400	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1401	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
1402	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
1403		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1404				data->nrg_silence_rssi[cnt]);
1405	}
1406	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1407	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1408			data->nrg_silence_ref);
1409	pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1410			data->nrg_energy_idx);
1411	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1412			data->nrg_silence_idx);
1413	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1414			data->nrg_th_cck);
1415	pos += scnprintf(buf + pos, bufsz - pos,
1416			"nrg_auto_corr_silence_diff:\t %u\n",
1417			data->nrg_auto_corr_silence_diff);
1418	pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1419			data->num_in_cck_no_fa);
1420	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1421			data->nrg_th_ofdm);
1422
1423	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1424	kfree(buf);
1425	return ret;
1426}
1427
1428
1429static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
1430					char __user *user_buf,
1431					size_t count, loff_t *ppos) {
1432
1433	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1434	int pos = 0;
1435	int cnt = 0;
1436	char *buf;
1437	int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
1438	ssize_t ret;
1439	struct iwl_chain_noise_data *data;
1440
1441	data = &priv->chain_noise_data;
1442	buf = kzalloc(bufsz, GFP_KERNEL);
1443	if (!buf) {
1444		IWL_ERR(priv, "Can not allocate Buffer\n");
1445		return -ENOMEM;
1446	}
1447
1448	pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1449			data->active_chains);
1450	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1451			data->chain_noise_a);
1452	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1453			data->chain_noise_b);
1454	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1455			data->chain_noise_c);
1456	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1457			data->chain_signal_a);
1458	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1459			data->chain_signal_b);
1460	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1461			data->chain_signal_c);
1462	pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1463			data->beacon_count);
1464
1465	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1466	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1467		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1468				data->disconn_array[cnt]);
1469	}
1470	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1471	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1472	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1473		pos += scnprintf(buf + pos, bufsz - pos, " %u",
1474				data->delta_gain_code[cnt]);
1475	}
1476	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1477	pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1478			data->radio_write);
1479	pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1480			data->state);
1481
1482	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1483	kfree(buf);
1484	return ret;
1485}
1486
1487DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
1488DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
1489DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1490DEBUGFS_READ_FILE_OPS(rx_queue);
1491DEBUGFS_READ_FILE_OPS(tx_queue);
1492DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1493DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1494DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1495DEBUGFS_READ_FILE_OPS(sensitivity);
1496DEBUGFS_READ_FILE_OPS(chain_noise);
1497
1498/*
1499 * Create the debugfs files and directories
1500 *
1501 */
1502int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1503{
1504	struct iwl_debugfs *dbgfs;
1505	struct dentry *phyd = priv->hw->wiphy->debugfsdir;
1506	int ret = 0;
1507
1508	dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
1509	if (!dbgfs) {
1510		ret = -ENOMEM;
1511		goto err;
1512	}
1513
1514	priv->dbgfs = dbgfs;
1515	dbgfs->name = name;
1516	dbgfs->dir_drv = debugfs_create_dir(name, phyd);
1517	if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
1518		ret = -ENOENT;
1519		goto err;
1520	}
1521
1522	DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
1523	DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
1524	DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
1525	DEBUGFS_ADD_FILE(nvm, data);
1526	DEBUGFS_ADD_FILE(sram, data);
1527	DEBUGFS_ADD_FILE(log_event, data);
1528	DEBUGFS_ADD_FILE(stations, data);
1529	DEBUGFS_ADD_FILE(channels, data);
1530	DEBUGFS_ADD_FILE(status, data);
1531	DEBUGFS_ADD_FILE(interrupt, data);
1532	DEBUGFS_ADD_FILE(qos, data);
1533#ifdef CONFIG_IWLWIFI_LEDS
1534	DEBUGFS_ADD_FILE(led, data);
1535#endif
1536	DEBUGFS_ADD_FILE(thermal_throttling, data);
1537	DEBUGFS_ADD_FILE(disable_ht40, data);
1538	DEBUGFS_ADD_FILE(rx_statistics, debug);
1539	DEBUGFS_ADD_FILE(tx_statistics, debug);
1540	DEBUGFS_ADD_FILE(traffic_log, debug);
1541	DEBUGFS_ADD_FILE(rx_queue, debug);
1542	DEBUGFS_ADD_FILE(tx_queue, debug);
1543	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1544		DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
1545		DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
1546		DEBUGFS_ADD_FILE(ucode_general_stats, debug);
1547		DEBUGFS_ADD_FILE(sensitivity, debug);
1548		DEBUGFS_ADD_FILE(chain_noise, debug);
1549	}
1550	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
1551	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
1552			 &priv->disable_chain_noise_cal);
1553	if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
1554	    ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
1555		DEBUGFS_ADD_BOOL(disable_tx_power, rf,
1556				&priv->disable_tx_power_cal);
1557	return 0;
1558
1559err:
1560	IWL_ERR(priv, "Can't open the debugfs directory\n");
1561	iwl_dbgfs_unregister(priv);
1562	return ret;
1563}
1564EXPORT_SYMBOL(iwl_dbgfs_register);
1565
1566/**
1567 * Remove the debugfs files and directories
1568 *
1569 */
1570void iwl_dbgfs_unregister(struct iwl_priv *priv)
1571{
1572	if (!priv->dbgfs)
1573		return;
1574
1575	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
1576	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
1577	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
1578	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
1579	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
1580	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
1581	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
1582	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
1583#ifdef CONFIG_IWLWIFI_LEDS
1584	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
1585#endif
1586	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
1587	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
1588	DEBUGFS_REMOVE(priv->dbgfs->dir_data);
1589	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
1590	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
1591	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
1592	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
1593	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
1594	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1595		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1596			file_ucode_rx_stats);
1597		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1598			file_ucode_tx_stats);
1599		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1600			file_ucode_general_stats);
1601		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1602			file_sensitivity);
1603		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1604			file_chain_noise);
1605	}
1606	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
1607	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
1608	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
1609	if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
1610	    ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
1611		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
1612	DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
1613	DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
1614	kfree(priv->dbgfs);
1615	priv->dbgfs = NULL;
1616}
1617EXPORT_SYMBOL(iwl_dbgfs_unregister);
1618
1619
1620
1621