iwl-debugfs.c revision e8fe59aecb9020b06305be4f8c67d73cbf49cbd2
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
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->power_data.tt;
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			(priv->power_data.adv_tt)
717			? "Advance" : "Legacy");
718	pos += scnprintf(buf + pos, bufsz - pos,
719			"Thermal Throttling State: %d\n",
720			tt->state);
721	if (priv->power_data.adv_tt) {
722		restriction = tt->restriction + tt->state;
723		pos += scnprintf(buf + pos, bufsz - pos,
724				"Tx mode: %d\n",
725				restriction->tx_stream);
726		pos += scnprintf(buf + pos, bufsz - pos,
727				"Rx mode: %d\n",
728				restriction->rx_stream);
729		pos += scnprintf(buf + pos, bufsz - pos,
730				"HT mode: %d\n",
731				restriction->is_ht);
732	}
733	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
734	return ret;
735}
736
737static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
738					 const char __user *user_buf,
739					 size_t count, loff_t *ppos)
740{
741	struct iwl_priv *priv = file->private_data;
742	char buf[8];
743	int buf_size;
744	int ht40;
745
746	memset(buf, 0, sizeof(buf));
747	buf_size = min(count, sizeof(buf) -  1);
748	if (copy_from_user(buf, user_buf, buf_size))
749		return -EFAULT;
750	if (sscanf(buf, "%d", &ht40) != 1)
751		return -EFAULT;
752	if (!iwl_is_associated(priv))
753		priv->disable_ht40 = ht40 ? true : false;
754	else {
755		IWL_ERR(priv, "Sta associated with AP - "
756			"Change to 40MHz channel support is not allowed\n");
757		return -EINVAL;
758	}
759
760	return count;
761}
762
763static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
764					 char __user *user_buf,
765					 size_t count, loff_t *ppos)
766{
767	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
768	char buf[100];
769	int pos = 0;
770	const size_t bufsz = sizeof(buf);
771	ssize_t ret;
772
773	pos += scnprintf(buf + pos, bufsz - pos,
774			"11n 40MHz Mode: %s\n",
775			priv->disable_ht40 ? "Disabled" : "Enabled");
776	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
777	return ret;
778}
779
780DEBUGFS_READ_WRITE_FILE_OPS(sram);
781DEBUGFS_WRITE_FILE_OPS(log_event);
782DEBUGFS_READ_FILE_OPS(nvm);
783DEBUGFS_READ_FILE_OPS(stations);
784DEBUGFS_READ_FILE_OPS(channels);
785DEBUGFS_READ_FILE_OPS(status);
786DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
787DEBUGFS_READ_FILE_OPS(qos);
788#ifdef CONFIG_IWLWIFI_LEDS
789DEBUGFS_READ_FILE_OPS(led);
790#endif
791DEBUGFS_READ_FILE_OPS(thermal_throttling);
792DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
793
794static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
795					 char __user *user_buf,
796					 size_t count, loff_t *ppos)
797{
798	struct iwl_priv *priv = file->private_data;
799	int pos = 0, ofs = 0;
800	int cnt = 0, entry;
801	struct iwl_tx_queue *txq;
802	struct iwl_queue *q;
803	struct iwl_rx_queue *rxq = &priv->rxq;
804	char *buf;
805	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
806		(IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
807	const u8 *ptr;
808	ssize_t ret;
809
810	buf = kzalloc(bufsz, GFP_KERNEL);
811	if (!buf) {
812		IWL_ERR(priv, "Can not allocate buffer\n");
813		return -ENOMEM;
814	}
815	pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
816	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
817		txq = &priv->txq[cnt];
818		q = &txq->q;
819		pos += scnprintf(buf + pos, bufsz - pos,
820				"q[%d]: read_ptr: %u, write_ptr: %u\n",
821				cnt, q->read_ptr, q->write_ptr);
822	}
823	if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
824		ptr = priv->tx_traffic;
825		pos += scnprintf(buf + pos, bufsz - pos,
826				"Tx Traffic idx: %u\n",	priv->tx_traffic_idx);
827		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
828			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
829			     entry++,  ofs += 16) {
830				pos += scnprintf(buf + pos, bufsz - pos,
831						"0x%.4x ", ofs);
832				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
833						   buf + pos, bufsz - pos, 0);
834				pos += strlen(buf);
835				if (bufsz - pos > 0)
836					buf[pos++] = '\n';
837			}
838		}
839	}
840
841	pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
842	pos += scnprintf(buf + pos, bufsz - pos,
843			"read: %u, write: %u\n",
844			 rxq->read, rxq->write);
845
846	if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
847		ptr = priv->rx_traffic;
848		pos += scnprintf(buf + pos, bufsz - pos,
849				"Rx Traffic idx: %u\n",	priv->rx_traffic_idx);
850		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
851			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
852			     entry++,  ofs += 16) {
853				pos += scnprintf(buf + pos, bufsz - pos,
854						"0x%.4x ", ofs);
855				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
856						   buf + pos, bufsz - pos, 0);
857				pos += strlen(buf);
858				if (bufsz - pos > 0)
859					buf[pos++] = '\n';
860			}
861		}
862	}
863
864	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
865	kfree(buf);
866	return ret;
867}
868
869static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
870					 const char __user *user_buf,
871					 size_t count, loff_t *ppos)
872{
873	struct iwl_priv *priv = file->private_data;
874	char buf[8];
875	int buf_size;
876	int traffic_log;
877
878	memset(buf, 0, sizeof(buf));
879	buf_size = min(count, sizeof(buf) -  1);
880	if (copy_from_user(buf, user_buf, buf_size))
881		return -EFAULT;
882	if (sscanf(buf, "%d", &traffic_log) != 1)
883		return -EFAULT;
884	if (traffic_log == 0)
885		iwl_reset_traffic_log(priv);
886
887	return count;
888}
889
890static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
891						char __user *user_buf,
892						size_t count, loff_t *ppos) {
893
894	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
895	struct iwl_tx_queue *txq;
896	struct iwl_queue *q;
897	char *buf;
898	int pos = 0;
899	int cnt;
900	int ret;
901	const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
902
903	buf = kzalloc(bufsz, GFP_KERNEL);
904	if (!buf)
905		return -ENOMEM;
906
907	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
908		txq = &priv->txq[cnt];
909		q = &txq->q;
910		pos += scnprintf(buf + pos, bufsz - pos,
911				"hwq %.2d: read=%u write=%u stop=%d"
912				" swq_id=%#.2x (ac %d/hwq %d)\n",
913				cnt, q->read_ptr, q->write_ptr,
914				!!test_bit(cnt, priv->queue_stopped),
915				txq->swq_id,
916				txq->swq_id & 0x80 ? txq->swq_id & 3 :
917				txq->swq_id,
918				txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
919				0x1f : txq->swq_id);
920		if (cnt >= 4)
921			continue;
922		/* for the ACs, display the stop count too */
923		pos += scnprintf(buf + pos, bufsz - pos,
924				"        stop-count: %d\n",
925				atomic_read(&priv->queue_stop_count[cnt]));
926	}
927	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
928	kfree(buf);
929	return ret;
930}
931
932static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
933						char __user *user_buf,
934						size_t count, loff_t *ppos) {
935
936	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
937	struct iwl_rx_queue *rxq = &priv->rxq;
938	char buf[256];
939	int pos = 0;
940	const size_t bufsz = sizeof(buf);
941
942	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
943						rxq->read);
944	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
945						rxq->write);
946	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
947						rxq->free_count);
948	pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
949			 le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
950	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
951}
952
953#define UCODE_STATISTICS_CLEAR_MSK		(0x1 << 0)
954#define UCODE_STATISTICS_FREQUENCY_MSK		(0x1 << 1)
955#define UCODE_STATISTICS_NARROW_BAND_MSK	(0x1 << 2)
956
957static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
958				     int bufsz)
959{
960	int p = 0;
961
962	p += scnprintf(buf + p, bufsz - p,
963		"Statistics Flag(0x%X):\n",
964		le32_to_cpu(priv->statistics.flag));
965	if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
966		p += scnprintf(buf + p, bufsz - p,
967		"\tStatistics have been cleared\n");
968	p += scnprintf(buf + p, bufsz - p,
969		"\tOperational Frequency: %s\n",
970		(le32_to_cpu(priv->statistics.flag) &
971		UCODE_STATISTICS_FREQUENCY_MSK)
972		 ? "2.4 GHz" : "5.2 GHz");
973	p += scnprintf(buf + p, bufsz - p,
974		"\tTGj Narrow Band: %s\n",
975		(le32_to_cpu(priv->statistics.flag) &
976		UCODE_STATISTICS_NARROW_BAND_MSK)
977		 ? "enabled" : "disabled");
978	return p;
979}
980
981
982static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
983					char __user *user_buf,
984					size_t count, loff_t *ppos)
985{
986	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
987	int pos = 0;
988	char *buf;
989	int bufsz = sizeof(struct statistics_rx_phy) * 20 +
990		sizeof(struct statistics_rx_non_phy) * 20 +
991		sizeof(struct statistics_rx_ht_phy) * 20 + 400;
992	ssize_t ret;
993	struct statistics_rx_phy *ofdm;
994	struct statistics_rx_phy *cck;
995	struct statistics_rx_non_phy *general;
996	struct statistics_rx_ht_phy *ht;
997
998	if (!iwl_is_alive(priv))
999		return -EAGAIN;
1000
1001	/* make request to uCode to retrieve statistics information */
1002	mutex_lock(&priv->mutex);
1003	ret = iwl_send_statistics_request(priv, 0);
1004	mutex_unlock(&priv->mutex);
1005
1006	if (ret) {
1007		IWL_ERR(priv,
1008			"Error sending statistics request: %zd\n", ret);
1009		return -EAGAIN;
1010	}
1011	buf = kzalloc(bufsz, GFP_KERNEL);
1012	if (!buf) {
1013		IWL_ERR(priv, "Can not allocate Buffer\n");
1014		return -ENOMEM;
1015	}
1016
1017	/* the statistic information display here is based on
1018	 * the last statistics notification from uCode
1019	 * might not reflect the current uCode activity
1020	 */
1021	ofdm = &priv->statistics.rx.ofdm;
1022	cck = &priv->statistics.rx.cck;
1023	general = &priv->statistics.rx.general;
1024	ht = &priv->statistics.rx.ofdm_ht;
1025	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1026	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
1027	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1028			 le32_to_cpu(ofdm->ina_cnt));
1029	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1030			 le32_to_cpu(ofdm->fina_cnt));
1031	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1032			 le32_to_cpu(ofdm->plcp_err));
1033	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1034			 le32_to_cpu(ofdm->crc32_err));
1035	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1036			 le32_to_cpu(ofdm->overrun_err));
1037	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1038			 le32_to_cpu(ofdm->early_overrun_err));
1039	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1040			 le32_to_cpu(ofdm->crc32_good));
1041	pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1042			 le32_to_cpu(ofdm->false_alarm_cnt));
1043	pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1044			 le32_to_cpu(ofdm->fina_sync_err_cnt));
1045	pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1046			 le32_to_cpu(ofdm->sfd_timeout));
1047	pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1048			 le32_to_cpu(ofdm->fina_timeout));
1049	pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1050			 le32_to_cpu(ofdm->unresponded_rts));
1051	pos += scnprintf(buf + pos, bufsz - pos,
1052			"rxe_frame_limit_overrun: %u\n",
1053			le32_to_cpu(ofdm->rxe_frame_limit_overrun));
1054	pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1055			 le32_to_cpu(ofdm->sent_ack_cnt));
1056	pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1057			 le32_to_cpu(ofdm->sent_cts_cnt));
1058	pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1059			 le32_to_cpu(ofdm->sent_ba_rsp_cnt));
1060	pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1061			 le32_to_cpu(ofdm->dsp_self_kill));
1062	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1063			 le32_to_cpu(ofdm->mh_format_err));
1064	pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1065			 le32_to_cpu(ofdm->re_acq_main_rssi_sum));
1066
1067	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
1068	pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1069			 le32_to_cpu(cck->ina_cnt));
1070	pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1071			 le32_to_cpu(cck->fina_cnt));
1072	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1073			 le32_to_cpu(cck->plcp_err));
1074	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1075			 le32_to_cpu(cck->crc32_err));
1076	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1077			 le32_to_cpu(cck->overrun_err));
1078	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1079			 le32_to_cpu(cck->early_overrun_err));
1080	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1081			 le32_to_cpu(cck->crc32_good));
1082	pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1083			 le32_to_cpu(cck->false_alarm_cnt));
1084	pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1085			 le32_to_cpu(cck->fina_sync_err_cnt));
1086	pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1087			 le32_to_cpu(cck->sfd_timeout));
1088	pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1089			 le32_to_cpu(cck->fina_timeout));
1090	pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1091			 le32_to_cpu(cck->unresponded_rts));
1092	pos += scnprintf(buf + pos, bufsz - pos,
1093			"rxe_frame_limit_overrun: %u\n",
1094			le32_to_cpu(cck->rxe_frame_limit_overrun));
1095	pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1096			 le32_to_cpu(cck->sent_ack_cnt));
1097	pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1098			 le32_to_cpu(cck->sent_cts_cnt));
1099	pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1100			 le32_to_cpu(cck->sent_ba_rsp_cnt));
1101	pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1102			 le32_to_cpu(cck->dsp_self_kill));
1103	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1104			 le32_to_cpu(cck->mh_format_err));
1105	pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1106			 le32_to_cpu(cck->re_acq_main_rssi_sum));
1107
1108	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
1109	pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
1110			 le32_to_cpu(general->bogus_cts));
1111	pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
1112			 le32_to_cpu(general->bogus_ack));
1113	pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
1114			 le32_to_cpu(general->non_bssid_frames));
1115	pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
1116			 le32_to_cpu(general->filtered_frames));
1117	pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
1118			 le32_to_cpu(general->non_channel_beacons));
1119	pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
1120			 le32_to_cpu(general->channel_beacons));
1121	pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
1122			 le32_to_cpu(general->num_missed_bcon));
1123	pos += scnprintf(buf + pos, bufsz - pos,
1124			"adc_rx_saturation_time: %u\n",
1125			le32_to_cpu(general->adc_rx_saturation_time));
1126	pos += scnprintf(buf + pos, bufsz - pos,
1127			"ina_detection_search_time: %u\n",
1128			le32_to_cpu(general->ina_detection_search_time));
1129	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
1130			 le32_to_cpu(general->beacon_silence_rssi_a));
1131	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
1132			 le32_to_cpu(general->beacon_silence_rssi_b));
1133	pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
1134			 le32_to_cpu(general->beacon_silence_rssi_c));
1135	pos += scnprintf(buf + pos, bufsz - pos,
1136			"interference_data_flag: %u\n",
1137			le32_to_cpu(general->interference_data_flag));
1138	pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
1139			 le32_to_cpu(general->channel_load));
1140	pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
1141			 le32_to_cpu(general->dsp_false_alarms));
1142	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
1143			 le32_to_cpu(general->beacon_rssi_a));
1144	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
1145			 le32_to_cpu(general->beacon_rssi_b));
1146	pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
1147			 le32_to_cpu(general->beacon_rssi_c));
1148	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
1149			 le32_to_cpu(general->beacon_energy_a));
1150	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
1151			 le32_to_cpu(general->beacon_energy_b));
1152	pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
1153			 le32_to_cpu(general->beacon_energy_c));
1154
1155	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
1156	pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1157			 le32_to_cpu(ht->plcp_err));
1158	pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1159			 le32_to_cpu(ht->overrun_err));
1160	pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1161			 le32_to_cpu(ht->early_overrun_err));
1162	pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1163			 le32_to_cpu(ht->crc32_good));
1164	pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1165			 le32_to_cpu(ht->crc32_err));
1166	pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1167			 le32_to_cpu(ht->mh_format_err));
1168	pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
1169			 le32_to_cpu(ht->agg_crc32_good));
1170	pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
1171			 le32_to_cpu(ht->agg_mpdu_cnt));
1172	pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
1173			 le32_to_cpu(ht->agg_cnt));
1174
1175	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1176	kfree(buf);
1177	return ret;
1178}
1179
1180static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1181					char __user *user_buf,
1182					size_t count, loff_t *ppos)
1183{
1184	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1185	int pos = 0;
1186	char *buf;
1187	int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
1188	ssize_t ret;
1189	struct statistics_tx *tx;
1190
1191	if (!iwl_is_alive(priv))
1192		return -EAGAIN;
1193
1194	/* make request to uCode to retrieve statistics information */
1195	mutex_lock(&priv->mutex);
1196	ret = iwl_send_statistics_request(priv, 0);
1197	mutex_unlock(&priv->mutex);
1198
1199	if (ret) {
1200		IWL_ERR(priv,
1201			"Error sending statistics request: %zd\n", ret);
1202		return -EAGAIN;
1203	}
1204	buf = kzalloc(bufsz, GFP_KERNEL);
1205	if (!buf) {
1206		IWL_ERR(priv, "Can not allocate Buffer\n");
1207		return -ENOMEM;
1208	}
1209
1210	/* the statistic information display here is based on
1211	 * the last statistics notification from uCode
1212	 * might not reflect the current uCode activity
1213	 */
1214	tx = &priv->statistics.tx;
1215	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1216	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
1217	pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
1218			 le32_to_cpu(tx->preamble_cnt));
1219	pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
1220			 le32_to_cpu(tx->rx_detected_cnt));
1221	pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
1222			 le32_to_cpu(tx->bt_prio_defer_cnt));
1223	pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
1224			 le32_to_cpu(tx->bt_prio_kill_cnt));
1225	pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
1226			 le32_to_cpu(tx->few_bytes_cnt));
1227	pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
1228			 le32_to_cpu(tx->cts_timeout));
1229	pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
1230			 le32_to_cpu(tx->ack_timeout));
1231	pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
1232			 le32_to_cpu(tx->expected_ack_cnt));
1233	pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
1234			 le32_to_cpu(tx->actual_ack_cnt));
1235	pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
1236			 le32_to_cpu(tx->dump_msdu_cnt));
1237	pos += scnprintf(buf + pos, bufsz - pos,
1238			"burst_abort_next_frame_mismatch_cnt: %u\n",
1239			le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
1240	pos += scnprintf(buf + pos, bufsz - pos,
1241			"burst_abort_missing_next_frame_cnt: %u\n",
1242			le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
1243	pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
1244			 le32_to_cpu(tx->cts_timeout_collision));
1245	pos += scnprintf(buf + pos, bufsz - pos,
1246			"ack_or_ba_timeout_collision: %u\n",
1247			le32_to_cpu(tx->ack_or_ba_timeout_collision));
1248	pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
1249			 le32_to_cpu(tx->agg.ba_timeout));
1250	pos += scnprintf(buf + pos, bufsz - pos,
1251			"agg ba_reschedule_frames: %u\n",
1252			le32_to_cpu(tx->agg.ba_reschedule_frames));
1253	pos += scnprintf(buf + pos, bufsz - pos,
1254			"agg scd_query_agg_frame_cnt: %u\n",
1255			le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
1256	pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
1257			 le32_to_cpu(tx->agg.scd_query_no_agg));
1258	pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
1259			 le32_to_cpu(tx->agg.scd_query_agg));
1260	pos += scnprintf(buf + pos, bufsz - pos,
1261			"agg scd_query_mismatch: %u\n",
1262			le32_to_cpu(tx->agg.scd_query_mismatch));
1263	pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
1264			 le32_to_cpu(tx->agg.frame_not_ready));
1265	pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
1266			 le32_to_cpu(tx->agg.underrun));
1267	pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
1268			 le32_to_cpu(tx->agg.bt_prio_kill));
1269	pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
1270			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
1271
1272	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1273	kfree(buf);
1274	return ret;
1275}
1276
1277static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1278					char __user *user_buf,
1279					size_t count, loff_t *ppos)
1280{
1281	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1282	int pos = 0;
1283	char *buf;
1284	int bufsz = sizeof(struct statistics_general) * 4 + 250;
1285	ssize_t ret;
1286	struct statistics_general *general;
1287	struct statistics_dbg *dbg;
1288	struct statistics_div *div;
1289
1290	if (!iwl_is_alive(priv))
1291		return -EAGAIN;
1292
1293	/* make request to uCode to retrieve statistics information */
1294	mutex_lock(&priv->mutex);
1295	ret = iwl_send_statistics_request(priv, 0);
1296	mutex_unlock(&priv->mutex);
1297
1298	if (ret) {
1299		IWL_ERR(priv,
1300			"Error sending statistics request: %zd\n", ret);
1301		return -EAGAIN;
1302	}
1303	buf = kzalloc(bufsz, GFP_KERNEL);
1304	if (!buf) {
1305		IWL_ERR(priv, "Can not allocate Buffer\n");
1306		return -ENOMEM;
1307	}
1308
1309	/* the statistic information display here is based on
1310	 * the last statistics notification from uCode
1311	 * might not reflect the current uCode activity
1312	 */
1313	general = &priv->statistics.general;
1314	dbg = &priv->statistics.general.dbg;
1315	div = &priv->statistics.general.div;
1316	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1317	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
1318	pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
1319			 le32_to_cpu(general->temperature));
1320	pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
1321			 le32_to_cpu(general->temperature_m));
1322	pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
1323			 le32_to_cpu(dbg->burst_check));
1324	pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
1325			 le32_to_cpu(dbg->burst_count));
1326	pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
1327			 le32_to_cpu(general->sleep_time));
1328	pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
1329			 le32_to_cpu(general->slots_out));
1330	pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
1331			 le32_to_cpu(general->slots_idle));
1332	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
1333			 le32_to_cpu(general->ttl_timestamp));
1334	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
1335			 le32_to_cpu(div->tx_on_a));
1336	pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
1337			 le32_to_cpu(div->tx_on_b));
1338	pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
1339			 le32_to_cpu(div->exec_time));
1340	pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
1341			 le32_to_cpu(div->probe_time));
1342	pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
1343			 le32_to_cpu(general->rx_enable_counter));
1344	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1345	kfree(buf);
1346	return ret;
1347}
1348
1349DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
1350DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
1351DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1352DEBUGFS_READ_FILE_OPS(rx_queue);
1353DEBUGFS_READ_FILE_OPS(tx_queue);
1354DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1355DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1356DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1357
1358/*
1359 * Create the debugfs files and directories
1360 *
1361 */
1362int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1363{
1364	struct iwl_debugfs *dbgfs;
1365	struct dentry *phyd = priv->hw->wiphy->debugfsdir;
1366	int ret = 0;
1367
1368	dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
1369	if (!dbgfs) {
1370		ret = -ENOMEM;
1371		goto err;
1372	}
1373
1374	priv->dbgfs = dbgfs;
1375	dbgfs->name = name;
1376	dbgfs->dir_drv = debugfs_create_dir(name, phyd);
1377	if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
1378		ret = -ENOENT;
1379		goto err;
1380	}
1381
1382	DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
1383	DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
1384	DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
1385	DEBUGFS_ADD_FILE(nvm, data);
1386	DEBUGFS_ADD_FILE(sram, data);
1387	DEBUGFS_ADD_FILE(log_event, data);
1388	DEBUGFS_ADD_FILE(stations, data);
1389	DEBUGFS_ADD_FILE(channels, data);
1390	DEBUGFS_ADD_FILE(status, data);
1391	DEBUGFS_ADD_FILE(interrupt, data);
1392	DEBUGFS_ADD_FILE(qos, data);
1393#ifdef CONFIG_IWLWIFI_LEDS
1394	DEBUGFS_ADD_FILE(led, data);
1395#endif
1396	DEBUGFS_ADD_FILE(thermal_throttling, data);
1397	DEBUGFS_ADD_FILE(disable_ht40, data);
1398	DEBUGFS_ADD_FILE(rx_statistics, debug);
1399	DEBUGFS_ADD_FILE(tx_statistics, debug);
1400	DEBUGFS_ADD_FILE(traffic_log, debug);
1401	DEBUGFS_ADD_FILE(rx_queue, debug);
1402	DEBUGFS_ADD_FILE(tx_queue, debug);
1403	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1404		DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
1405		DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
1406		DEBUGFS_ADD_FILE(ucode_general_stats, debug);
1407	}
1408	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
1409	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
1410			 &priv->disable_chain_noise_cal);
1411	if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
1412	    ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
1413		DEBUGFS_ADD_BOOL(disable_tx_power, rf,
1414				&priv->disable_tx_power_cal);
1415	return 0;
1416
1417err:
1418	IWL_ERR(priv, "Can't open the debugfs directory\n");
1419	iwl_dbgfs_unregister(priv);
1420	return ret;
1421}
1422EXPORT_SYMBOL(iwl_dbgfs_register);
1423
1424/**
1425 * Remove the debugfs files and directories
1426 *
1427 */
1428void iwl_dbgfs_unregister(struct iwl_priv *priv)
1429{
1430	if (!priv->dbgfs)
1431		return;
1432
1433	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
1434	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
1435	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
1436	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
1437	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
1438	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
1439	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
1440	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
1441#ifdef CONFIG_IWLWIFI_LEDS
1442	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
1443#endif
1444	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
1445	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
1446	DEBUGFS_REMOVE(priv->dbgfs->dir_data);
1447	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
1448	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
1449	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
1450	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
1451	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
1452	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1453		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1454			file_ucode_rx_stats);
1455		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1456			file_ucode_tx_stats);
1457		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1458			file_ucode_general_stats);
1459	}
1460	DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
1461	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
1462	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
1463	if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
1464	    ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
1465		DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
1466	DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
1467	DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
1468	kfree(priv->dbgfs);
1469	priv->dbgfs = NULL;
1470}
1471EXPORT_SYMBOL(iwl_dbgfs_unregister);
1472
1473
1474
1475