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