1 /******************************************************************************
2  *
3  * GPL LICENSE SUMMARY
4  *
5  * Copyright(c) 2008 - 2011 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 #include <linux/ieee80211.h>
29 #include <linux/export.h>
30 #include <net/mac80211.h>
31 
32 #include "common.h"
33 
34 static void
35 il_clear_traffic_stats(struct il_priv *il)
36 {
37 	memset(&il->tx_stats, 0, sizeof(struct traffic_stats));
38 	memset(&il->rx_stats, 0, sizeof(struct traffic_stats));
39 }
40 
41 /*
42  * il_update_stats function record all the MGMT, CTRL and DATA pkt for
43  * both TX and Rx . Use debugfs to display the rx/rx_stats
44  */
45 void
46 il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
47 {
48 	struct traffic_stats *stats;
49 
50 	if (is_tx)
51 		stats = &il->tx_stats;
52 	else
53 		stats = &il->rx_stats;
54 
55 	if (ieee80211_is_mgmt(fc)) {
56 		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
57 		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
58 			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
59 			break;
60 		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
61 			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
62 			break;
63 		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
64 			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
65 			break;
66 		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
67 			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
68 			break;
69 		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
70 			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
71 			break;
72 		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
73 			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
74 			break;
75 		case cpu_to_le16(IEEE80211_STYPE_BEACON):
76 			stats->mgmt[MANAGEMENT_BEACON]++;
77 			break;
78 		case cpu_to_le16(IEEE80211_STYPE_ATIM):
79 			stats->mgmt[MANAGEMENT_ATIM]++;
80 			break;
81 		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
82 			stats->mgmt[MANAGEMENT_DISASSOC]++;
83 			break;
84 		case cpu_to_le16(IEEE80211_STYPE_AUTH):
85 			stats->mgmt[MANAGEMENT_AUTH]++;
86 			break;
87 		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
88 			stats->mgmt[MANAGEMENT_DEAUTH]++;
89 			break;
90 		case cpu_to_le16(IEEE80211_STYPE_ACTION):
91 			stats->mgmt[MANAGEMENT_ACTION]++;
92 			break;
93 		}
94 	} else if (ieee80211_is_ctl(fc)) {
95 		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
96 		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
97 			stats->ctrl[CONTROL_BACK_REQ]++;
98 			break;
99 		case cpu_to_le16(IEEE80211_STYPE_BACK):
100 			stats->ctrl[CONTROL_BACK]++;
101 			break;
102 		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
103 			stats->ctrl[CONTROL_PSPOLL]++;
104 			break;
105 		case cpu_to_le16(IEEE80211_STYPE_RTS):
106 			stats->ctrl[CONTROL_RTS]++;
107 			break;
108 		case cpu_to_le16(IEEE80211_STYPE_CTS):
109 			stats->ctrl[CONTROL_CTS]++;
110 			break;
111 		case cpu_to_le16(IEEE80211_STYPE_ACK):
112 			stats->ctrl[CONTROL_ACK]++;
113 			break;
114 		case cpu_to_le16(IEEE80211_STYPE_CFEND):
115 			stats->ctrl[CONTROL_CFEND]++;
116 			break;
117 		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
118 			stats->ctrl[CONTROL_CFENDACK]++;
119 			break;
120 		}
121 	} else {
122 		/* data */
123 		stats->data_cnt++;
124 		stats->data_bytes += len;
125 	}
126 }
127 EXPORT_SYMBOL(il_update_stats);
128 
129 /* create and remove of files */
130 #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
131 	debugfs_create_file(#name, mode, parent, il,			\
132 			    &il_dbgfs_##name##_ops);			\
133 } while (0)
134 
135 #define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\
136 	debugfs_create_bool(#name, 0600, parent, ptr);			\
137 } while (0)
138 
139 /* file operation */
140 #define DEBUGFS_READ_FUNC(name)                                         \
141 static ssize_t il_dbgfs_##name##_read(struct file *file,               \
142 					char __user *user_buf,          \
143 					size_t count, loff_t *ppos);
144 
145 #define DEBUGFS_WRITE_FUNC(name)                                        \
146 static ssize_t il_dbgfs_##name##_write(struct file *file,              \
147 					const char __user *user_buf,    \
148 					size_t count, loff_t *ppos);
149 
150 
151 #define DEBUGFS_READ_FILE_OPS(name)				\
152 	DEBUGFS_READ_FUNC(name);				\
153 static const struct file_operations il_dbgfs_##name##_ops = {	\
154 	.read = il_dbgfs_##name##_read,				\
155 	.open = simple_open,					\
156 	.llseek = generic_file_llseek,				\
157 };
158 
159 #define DEBUGFS_WRITE_FILE_OPS(name)				\
160 	DEBUGFS_WRITE_FUNC(name);				\
161 static const struct file_operations il_dbgfs_##name##_ops = {	\
162 	.write = il_dbgfs_##name##_write,			\
163 	.open = simple_open,					\
164 	.llseek = generic_file_llseek,				\
165 };
166 
167 #define DEBUGFS_READ_WRITE_FILE_OPS(name)			\
168 	DEBUGFS_READ_FUNC(name);				\
169 	DEBUGFS_WRITE_FUNC(name);				\
170 static const struct file_operations il_dbgfs_##name##_ops = {	\
171 	.write = il_dbgfs_##name##_write,			\
172 	.read = il_dbgfs_##name##_read,				\
173 	.open = simple_open,					\
174 	.llseek = generic_file_llseek,				\
175 };
176 
177 static const char *
178 il_get_mgmt_string(int cmd)
179 {
180 	switch (cmd) {
181 	IL_CMD(MANAGEMENT_ASSOC_REQ);
182 	IL_CMD(MANAGEMENT_ASSOC_RESP);
183 	IL_CMD(MANAGEMENT_REASSOC_REQ);
184 	IL_CMD(MANAGEMENT_REASSOC_RESP);
185 	IL_CMD(MANAGEMENT_PROBE_REQ);
186 	IL_CMD(MANAGEMENT_PROBE_RESP);
187 	IL_CMD(MANAGEMENT_BEACON);
188 	IL_CMD(MANAGEMENT_ATIM);
189 	IL_CMD(MANAGEMENT_DISASSOC);
190 	IL_CMD(MANAGEMENT_AUTH);
191 	IL_CMD(MANAGEMENT_DEAUTH);
192 	IL_CMD(MANAGEMENT_ACTION);
193 	default:
194 		return "UNKNOWN";
195 
196 	}
197 }
198 
199 static const char *
200 il_get_ctrl_string(int cmd)
201 {
202 	switch (cmd) {
203 	IL_CMD(CONTROL_BACK_REQ);
204 	IL_CMD(CONTROL_BACK);
205 	IL_CMD(CONTROL_PSPOLL);
206 	IL_CMD(CONTROL_RTS);
207 	IL_CMD(CONTROL_CTS);
208 	IL_CMD(CONTROL_ACK);
209 	IL_CMD(CONTROL_CFEND);
210 	IL_CMD(CONTROL_CFENDACK);
211 	default:
212 		return "UNKNOWN";
213 
214 	}
215 }
216 
217 static ssize_t
218 il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,
219 		       loff_t *ppos)
220 {
221 
222 	struct il_priv *il = file->private_data;
223 	char *buf;
224 	int pos = 0;
225 
226 	int cnt;
227 	ssize_t ret;
228 	const size_t bufsz =
229 	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
230 	buf = kzalloc(bufsz, GFP_KERNEL);
231 	if (!buf)
232 		return -ENOMEM;
233 	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
234 	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
235 		pos +=
236 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
237 			      il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]);
238 	}
239 	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
240 	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
241 		pos +=
242 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
243 			      il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]);
244 	}
245 	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
246 	pos +=
247 	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
248 		      il->tx_stats.data_cnt);
249 	pos +=
250 	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
251 		      il->tx_stats.data_bytes);
252 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
253 	kfree(buf);
254 	return ret;
255 }
256 
257 static ssize_t
258 il_dbgfs_clear_traffic_stats_write(struct file *file,
259 				   const char __user *user_buf, size_t count,
260 				   loff_t *ppos)
261 {
262 	struct il_priv *il = file->private_data;
263 	u32 clear_flag;
264 	char buf[8];
265 	int buf_size;
266 
267 	memset(buf, 0, sizeof(buf));
268 	buf_size = min(count, sizeof(buf) - 1);
269 	if (copy_from_user(buf, user_buf, buf_size))
270 		return -EFAULT;
271 	if (sscanf(buf, "%x", &clear_flag) != 1)
272 		return -EFAULT;
273 	il_clear_traffic_stats(il);
274 
275 	return count;
276 }
277 
278 static ssize_t
279 il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,
280 		       loff_t *ppos)
281 {
282 
283 	struct il_priv *il = file->private_data;
284 	char *buf;
285 	int pos = 0;
286 	int cnt;
287 	ssize_t ret;
288 	const size_t bufsz =
289 	    100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
290 	buf = kzalloc(bufsz, GFP_KERNEL);
291 	if (!buf)
292 		return -ENOMEM;
293 
294 	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
295 	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
296 		pos +=
297 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
298 			      il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]);
299 	}
300 	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
301 	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
302 		pos +=
303 		    scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n",
304 			      il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]);
305 	}
306 	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
307 	pos +=
308 	    scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
309 		      il->rx_stats.data_cnt);
310 	pos +=
311 	    scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
312 		      il->rx_stats.data_bytes);
313 
314 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
315 	kfree(buf);
316 	return ret;
317 }
318 
319 #define BYTE1_MASK 0x000000ff;
320 #define BYTE2_MASK 0x0000ffff;
321 #define BYTE3_MASK 0x00ffffff;
322 static ssize_t
323 il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,
324 		   loff_t *ppos)
325 {
326 	u32 val;
327 	char *buf;
328 	ssize_t ret;
329 	int i;
330 	int pos = 0;
331 	struct il_priv *il = file->private_data;
332 	size_t bufsz;
333 
334 	/* default is to dump the entire data segment */
335 	if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) {
336 		il->dbgfs_sram_offset = 0x800000;
337 		if (il->ucode_type == UCODE_INIT)
338 			il->dbgfs_sram_len = il->ucode_init_data.len;
339 		else
340 			il->dbgfs_sram_len = il->ucode_data.len;
341 	}
342 	bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
343 	buf = kmalloc(bufsz, GFP_KERNEL);
344 	if (!buf)
345 		return -ENOMEM;
346 	pos +=
347 	    scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
348 		      il->dbgfs_sram_len);
349 	pos +=
350 	    scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
351 		      il->dbgfs_sram_offset);
352 	for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
353 		val =
354 		    il_read_targ_mem(il,
355 				     il->dbgfs_sram_offset +
356 				     il->dbgfs_sram_len - i);
357 		if (i < 4) {
358 			switch (i) {
359 			case 1:
360 				val &= BYTE1_MASK;
361 				break;
362 			case 2:
363 				val &= BYTE2_MASK;
364 				break;
365 			case 3:
366 				val &= BYTE3_MASK;
367 				break;
368 			}
369 		}
370 		if (!(i % 16))
371 			pos += scnprintf(buf + pos, bufsz - pos, "\n");
372 		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
373 	}
374 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
375 
376 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
377 	kfree(buf);
378 	return ret;
379 }
380 
381 static ssize_t
382 il_dbgfs_sram_write(struct file *file, const char __user *user_buf,
383 		    size_t count, loff_t *ppos)
384 {
385 	struct il_priv *il = file->private_data;
386 	char buf[64];
387 	int buf_size;
388 	u32 offset, len;
389 
390 	memset(buf, 0, sizeof(buf));
391 	buf_size = min(count, sizeof(buf) - 1);
392 	if (copy_from_user(buf, user_buf, buf_size))
393 		return -EFAULT;
394 
395 	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
396 		il->dbgfs_sram_offset = offset;
397 		il->dbgfs_sram_len = len;
398 	} else {
399 		il->dbgfs_sram_offset = 0;
400 		il->dbgfs_sram_len = 0;
401 	}
402 
403 	return count;
404 }
405 
406 static ssize_t
407 il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,
408 		       loff_t *ppos)
409 {
410 	struct il_priv *il = file->private_data;
411 	struct il_station_entry *station;
412 	int max_sta = il->hw_params.max_stations;
413 	char *buf;
414 	int i, j, pos = 0;
415 	ssize_t ret;
416 	/* Add 30 for initial string */
417 	const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
418 
419 	buf = kmalloc(bufsz, GFP_KERNEL);
420 	if (!buf)
421 		return -ENOMEM;
422 
423 	pos +=
424 	    scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
425 		      il->num_stations);
426 
427 	for (i = 0; i < max_sta; i++) {
428 		station = &il->stations[i];
429 		if (!station->used)
430 			continue;
431 		pos +=
432 		    scnprintf(buf + pos, bufsz - pos,
433 			      "station %d - addr: %pM, flags: %#x\n", i,
434 			      station->sta.sta.addr,
435 			      station->sta.station_flags_msk);
436 		pos +=
437 		    scnprintf(buf + pos, bufsz - pos,
438 			      "TID\tseq_num\ttxq_id\tframes\ttfds\t");
439 		pos +=
440 		    scnprintf(buf + pos, bufsz - pos,
441 			      "start_idx\tbitmap\t\t\trate_n_flags\n");
442 
443 		for (j = 0; j < MAX_TID_COUNT; j++) {
444 			pos +=
445 			    scnprintf(buf + pos, bufsz - pos,
446 				      "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
447 				      j, station->tid[j].seq_number,
448 				      station->tid[j].agg.txq_id,
449 				      station->tid[j].agg.frame_count,
450 				      station->tid[j].tfds_in_queue,
451 				      station->tid[j].agg.start_idx,
452 				      station->tid[j].agg.bitmap,
453 				      station->tid[j].agg.rate_n_flags);
454 
455 			if (station->tid[j].agg.wait_for_ba)
456 				pos +=
457 				    scnprintf(buf + pos, bufsz - pos,
458 					      " - waitforba");
459 			pos += scnprintf(buf + pos, bufsz - pos, "\n");
460 		}
461 
462 		pos += scnprintf(buf + pos, bufsz - pos, "\n");
463 	}
464 
465 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
466 	kfree(buf);
467 	return ret;
468 }
469 
470 static ssize_t
471 il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
472 		  loff_t *ppos)
473 {
474 	ssize_t ret;
475 	struct il_priv *il = file->private_data;
476 	int pos = 0, ofs = 0, buf_size = 0;
477 	const u8 *ptr;
478 	char *buf;
479 	u16 eeprom_ver;
480 	size_t eeprom_len = il->cfg->eeprom_size;
481 	buf_size = 4 * eeprom_len + 256;
482 
483 	if (eeprom_len % 16) {
484 		IL_ERR("NVM size is not multiple of 16.\n");
485 		return -ENODATA;
486 	}
487 
488 	ptr = il->eeprom;
489 	if (!ptr) {
490 		IL_ERR("Invalid EEPROM memory\n");
491 		return -ENOMEM;
492 	}
493 
494 	/* 4 characters for byte 0xYY */
495 	buf = kzalloc(buf_size, GFP_KERNEL);
496 	if (!buf) {
497 		IL_ERR("Can not allocate Buffer\n");
498 		return -ENOMEM;
499 	}
500 	eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
501 	pos +=
502 	    scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
503 		      eeprom_ver);
504 	for (ofs = 0; ofs < eeprom_len; ofs += 16) {
505 		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",
506 				 ofs, ptr + ofs);
507 	}
508 
509 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
510 	kfree(buf);
511 	return ret;
512 }
513 
514 static ssize_t
515 il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
516 		       loff_t *ppos)
517 {
518 	struct il_priv *il = file->private_data;
519 	struct ieee80211_channel *channels = NULL;
520 	const struct ieee80211_supported_band *supp_band = NULL;
521 	int pos = 0, i, bufsz = PAGE_SIZE;
522 	char *buf;
523 	ssize_t ret;
524 
525 	if (!test_bit(S_GEO_CONFIGURED, &il->status))
526 		return -EAGAIN;
527 
528 	buf = kzalloc(bufsz, GFP_KERNEL);
529 	if (!buf) {
530 		IL_ERR("Can not allocate Buffer\n");
531 		return -ENOMEM;
532 	}
533 
534 	supp_band = il_get_hw_mode(il, NL80211_BAND_2GHZ);
535 	if (supp_band) {
536 		channels = supp_band->channels;
537 
538 		pos +=
539 		    scnprintf(buf + pos, bufsz - pos,
540 			      "Displaying %d channels in 2.4GHz band 802.11bg):\n",
541 			      supp_band->n_channels);
542 
543 		for (i = 0; i < supp_band->n_channels; i++)
544 			pos +=
545 			    scnprintf(buf + pos, bufsz - pos,
546 				      "%d: %ddBm: BSS%s%s, %s.\n",
547 				      channels[i].hw_value,
548 				      channels[i].max_power,
549 				      channels[i].
550 				      flags & IEEE80211_CHAN_RADAR ?
551 				      " (IEEE 802.11h required)" : "",
552 				      ((channels[i].
553 					flags & IEEE80211_CHAN_NO_IR) ||
554 				       (channels[i].
555 					flags & IEEE80211_CHAN_RADAR)) ? "" :
556 				      ", IBSS",
557 				      channels[i].
558 				      flags & IEEE80211_CHAN_NO_IR ?
559 				      "passive only" : "active/passive");
560 	}
561 	supp_band = il_get_hw_mode(il, NL80211_BAND_5GHZ);
562 	if (supp_band) {
563 		channels = supp_band->channels;
564 
565 		pos +=
566 		    scnprintf(buf + pos, bufsz - pos,
567 			      "Displaying %d channels in 5.2GHz band (802.11a)\n",
568 			      supp_band->n_channels);
569 
570 		for (i = 0; i < supp_band->n_channels; i++)
571 			pos +=
572 			    scnprintf(buf + pos, bufsz - pos,
573 				      "%d: %ddBm: BSS%s%s, %s.\n",
574 				      channels[i].hw_value,
575 				      channels[i].max_power,
576 				      channels[i].
577 				      flags & IEEE80211_CHAN_RADAR ?
578 				      " (IEEE 802.11h required)" : "",
579 				      ((channels[i].
580 					flags & IEEE80211_CHAN_NO_IR) ||
581 				       (channels[i].
582 					flags & IEEE80211_CHAN_RADAR)) ? "" :
583 				      ", IBSS",
584 				      channels[i].
585 				      flags & IEEE80211_CHAN_NO_IR ?
586 				      "passive only" : "active/passive");
587 	}
588 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
589 	kfree(buf);
590 	return ret;
591 }
592 
593 static ssize_t
594 il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
595 		     loff_t *ppos)
596 {
597 
598 	struct il_priv *il = file->private_data;
599 	char buf[512];
600 	int pos = 0;
601 	const size_t bufsz = sizeof(buf);
602 
603 	pos +=
604 	    scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
605 		      test_bit(S_HCMD_ACTIVE, &il->status));
606 	pos +=
607 	    scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
608 		      test_bit(S_INT_ENABLED, &il->status));
609 	pos +=
610 	    scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n",
611 		      test_bit(S_RFKILL, &il->status));
612 	pos +=
613 	    scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
614 		      test_bit(S_CT_KILL, &il->status));
615 	pos +=
616 	    scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
617 		      test_bit(S_INIT, &il->status));
618 	pos +=
619 	    scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
620 		      test_bit(S_ALIVE, &il->status));
621 	pos +=
622 	    scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
623 		      test_bit(S_READY, &il->status));
624 	pos +=
625 	    scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
626 		      test_bit(S_TEMPERATURE, &il->status));
627 	pos +=
628 	    scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
629 		      test_bit(S_GEO_CONFIGURED, &il->status));
630 	pos +=
631 	    scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
632 		      test_bit(S_EXIT_PENDING, &il->status));
633 	pos +=
634 	    scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
635 		      test_bit(S_STATS, &il->status));
636 	pos +=
637 	    scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
638 		      test_bit(S_SCANNING, &il->status));
639 	pos +=
640 	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
641 		      test_bit(S_SCAN_ABORTING, &il->status));
642 	pos +=
643 	    scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
644 		      test_bit(S_SCAN_HW, &il->status));
645 	pos +=
646 	    scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
647 		      test_bit(S_POWER_PMI, &il->status));
648 	pos +=
649 	    scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
650 		      test_bit(S_FW_ERROR, &il->status));
651 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
652 }
653 
654 static ssize_t
655 il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
656 			loff_t *ppos)
657 {
658 
659 	struct il_priv *il = file->private_data;
660 	int pos = 0;
661 	int cnt = 0;
662 	char *buf;
663 	int bufsz = 24 * 64;	/* 24 items * 64 char per item */
664 	ssize_t ret;
665 
666 	buf = kzalloc(bufsz, GFP_KERNEL);
667 	if (!buf) {
668 		IL_ERR("Can not allocate Buffer\n");
669 		return -ENOMEM;
670 	}
671 
672 	pos +=
673 	    scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
674 
675 	pos +=
676 	    scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
677 		      il->isr_stats.hw);
678 	pos +=
679 	    scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
680 		      il->isr_stats.sw);
681 	if (il->isr_stats.sw || il->isr_stats.hw) {
682 		pos +=
683 		    scnprintf(buf + pos, bufsz - pos,
684 			      "\tLast Restarting Code:  0x%X\n",
685 			      il->isr_stats.err_code);
686 	}
687 #ifdef CONFIG_IWLEGACY_DEBUG
688 	pos +=
689 	    scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
690 		      il->isr_stats.sch);
691 	pos +=
692 	    scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
693 		      il->isr_stats.alive);
694 #endif
695 	pos +=
696 	    scnprintf(buf + pos, bufsz - pos,
697 		      "HW RF KILL switch toggled:\t %u\n",
698 		      il->isr_stats.rfkill);
699 
700 	pos +=
701 	    scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
702 		      il->isr_stats.ctkill);
703 
704 	pos +=
705 	    scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
706 		      il->isr_stats.wakeup);
707 
708 	pos +=
709 	    scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
710 		      il->isr_stats.rx);
711 	for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
712 		if (il->isr_stats.handlers[cnt] > 0)
713 			pos +=
714 			    scnprintf(buf + pos, bufsz - pos,
715 				      "\tRx handler[%36s]:\t\t %u\n",
716 				      il_get_cmd_string(cnt),
717 				      il->isr_stats.handlers[cnt]);
718 	}
719 
720 	pos +=
721 	    scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
722 		      il->isr_stats.tx);
723 
724 	pos +=
725 	    scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
726 		      il->isr_stats.unhandled);
727 
728 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
729 	kfree(buf);
730 	return ret;
731 }
732 
733 static ssize_t
734 il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
735 			 size_t count, loff_t *ppos)
736 {
737 	struct il_priv *il = file->private_data;
738 	char buf[8];
739 	int buf_size;
740 	u32 reset_flag;
741 
742 	memset(buf, 0, sizeof(buf));
743 	buf_size = min(count, sizeof(buf) - 1);
744 	if (copy_from_user(buf, user_buf, buf_size))
745 		return -EFAULT;
746 	if (sscanf(buf, "%x", &reset_flag) != 1)
747 		return -EFAULT;
748 	if (reset_flag == 0)
749 		il_clear_isr_stats(il);
750 
751 	return count;
752 }
753 
754 static ssize_t
755 il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
756 		  loff_t *ppos)
757 {
758 	struct il_priv *il = file->private_data;
759 	int pos = 0, i;
760 	char buf[256];
761 	const size_t bufsz = sizeof(buf);
762 
763 	for (i = 0; i < AC_NUM; i++) {
764 		pos +=
765 		    scnprintf(buf + pos, bufsz - pos,
766 			      "\tcw_min\tcw_max\taifsn\ttxop\n");
767 		pos +=
768 		    scnprintf(buf + pos, bufsz - pos,
769 			      "AC[%d]\t%u\t%u\t%u\t%u\n", i,
770 			      il->qos_data.def_qos_parm.ac[i].cw_min,
771 			      il->qos_data.def_qos_parm.ac[i].cw_max,
772 			      il->qos_data.def_qos_parm.ac[i].aifsn,
773 			      il->qos_data.def_qos_parm.ac[i].edca_txop);
774 	}
775 
776 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
777 }
778 
779 static ssize_t
780 il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
781 			    size_t count, loff_t *ppos)
782 {
783 	struct il_priv *il = file->private_data;
784 	char buf[8];
785 	int buf_size;
786 	int ht40;
787 
788 	memset(buf, 0, sizeof(buf));
789 	buf_size = min(count, sizeof(buf) - 1);
790 	if (copy_from_user(buf, user_buf, buf_size))
791 		return -EFAULT;
792 	if (sscanf(buf, "%d", &ht40) != 1)
793 		return -EFAULT;
794 	if (!il_is_any_associated(il))
795 		il->disable_ht40 = ht40 ? true : false;
796 	else {
797 		IL_ERR("Sta associated with AP - "
798 		       "Change to 40MHz channel support is not allowed\n");
799 		return -EINVAL;
800 	}
801 
802 	return count;
803 }
804 
805 static ssize_t
806 il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
807 			   size_t count, loff_t *ppos)
808 {
809 	struct il_priv *il = file->private_data;
810 	char buf[100];
811 	int pos = 0;
812 	const size_t bufsz = sizeof(buf);
813 
814 	pos +=
815 	    scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
816 		      il->disable_ht40 ? "Disabled" : "Enabled");
817 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
818 }
819 
820 DEBUGFS_READ_WRITE_FILE_OPS(sram);
821 DEBUGFS_READ_FILE_OPS(nvm);
822 DEBUGFS_READ_FILE_OPS(stations);
823 DEBUGFS_READ_FILE_OPS(channels);
824 DEBUGFS_READ_FILE_OPS(status);
825 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
826 DEBUGFS_READ_FILE_OPS(qos);
827 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
828 
829 static ssize_t
830 il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
831 		       loff_t *ppos)
832 {
833 
834 	struct il_priv *il = file->private_data;
835 	struct il_tx_queue *txq;
836 	struct il_queue *q;
837 	char *buf;
838 	int pos = 0;
839 	int cnt;
840 	int ret;
841 	const size_t bufsz =
842 	    sizeof(char) * 64 * il->cfg->num_of_queues;
843 
844 	if (!il->txq) {
845 		IL_ERR("txq not ready\n");
846 		return -EAGAIN;
847 	}
848 	buf = kzalloc(bufsz, GFP_KERNEL);
849 	if (!buf)
850 		return -ENOMEM;
851 
852 	for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
853 		txq = &il->txq[cnt];
854 		q = &txq->q;
855 		pos +=
856 		    scnprintf(buf + pos, bufsz - pos,
857 			      "hwq %.2d: read=%u write=%u stop=%d"
858 			      " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
859 			      q->read_ptr, q->write_ptr,
860 			      !!test_bit(cnt, il->queue_stopped),
861 			      txq->swq_id, txq->swq_id & 3,
862 			      (txq->swq_id >> 2) & 0x1f);
863 		if (cnt >= 4)
864 			continue;
865 		/* for the ACs, display the stop count too */
866 		pos +=
867 		    scnprintf(buf + pos, bufsz - pos,
868 			      "        stop-count: %d\n",
869 			      atomic_read(&il->queue_stop_count[cnt]));
870 	}
871 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
872 	kfree(buf);
873 	return ret;
874 }
875 
876 static ssize_t
877 il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
878 		       loff_t *ppos)
879 {
880 
881 	struct il_priv *il = file->private_data;
882 	struct il_rx_queue *rxq = &il->rxq;
883 	char buf[256];
884 	int pos = 0;
885 	const size_t bufsz = sizeof(buf);
886 
887 	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
888 	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
889 	pos +=
890 	    scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
891 		      rxq->free_count);
892 	if (rxq->rb_stts) {
893 		pos +=
894 		    scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
895 			      le16_to_cpu(rxq->rb_stts->
896 					  closed_rb_num) & 0x0FFF);
897 	} else {
898 		pos +=
899 		    scnprintf(buf + pos, bufsz - pos,
900 			      "closed_rb_num: Not Allocated\n");
901 	}
902 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
903 }
904 
905 static ssize_t
906 il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
907 			     size_t count, loff_t *ppos)
908 {
909 	struct il_priv *il = file->private_data;
910 
911 	return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos);
912 }
913 
914 static ssize_t
915 il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
916 			     size_t count, loff_t *ppos)
917 {
918 	struct il_priv *il = file->private_data;
919 
920 	return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos);
921 }
922 
923 static ssize_t
924 il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
925 				  size_t count, loff_t *ppos)
926 {
927 	struct il_priv *il = file->private_data;
928 
929 	return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos);
930 }
931 
932 static ssize_t
933 il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
934 			  size_t count, loff_t *ppos)
935 {
936 
937 	struct il_priv *il = file->private_data;
938 	int pos = 0;
939 	int cnt = 0;
940 	char *buf;
941 	int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
942 	ssize_t ret;
943 	struct il_sensitivity_data *data;
944 
945 	data = &il->sensitivity_data;
946 	buf = kzalloc(bufsz, GFP_KERNEL);
947 	if (!buf) {
948 		IL_ERR("Can not allocate Buffer\n");
949 		return -ENOMEM;
950 	}
951 
952 	pos +=
953 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
954 		      data->auto_corr_ofdm);
955 	pos +=
956 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
957 		      data->auto_corr_ofdm_mrc);
958 	pos +=
959 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
960 		      data->auto_corr_ofdm_x1);
961 	pos +=
962 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
963 		      data->auto_corr_ofdm_mrc_x1);
964 	pos +=
965 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
966 		      data->auto_corr_cck);
967 	pos +=
968 	    scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
969 		      data->auto_corr_cck_mrc);
970 	pos +=
971 	    scnprintf(buf + pos, bufsz - pos,
972 		      "last_bad_plcp_cnt_ofdm:\t\t %u\n",
973 		      data->last_bad_plcp_cnt_ofdm);
974 	pos +=
975 	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
976 		      data->last_fa_cnt_ofdm);
977 	pos +=
978 	    scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
979 		      data->last_bad_plcp_cnt_cck);
980 	pos +=
981 	    scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
982 		      data->last_fa_cnt_cck);
983 	pos +=
984 	    scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
985 		      data->nrg_curr_state);
986 	pos +=
987 	    scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
988 		      data->nrg_prev_state);
989 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
990 	for (cnt = 0; cnt < 10; cnt++) {
991 		pos +=
992 		    scnprintf(buf + pos, bufsz - pos, " %u",
993 			      data->nrg_value[cnt]);
994 	}
995 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
996 	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
997 	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
998 		pos +=
999 		    scnprintf(buf + pos, bufsz - pos, " %u",
1000 			      data->nrg_silence_rssi[cnt]);
1001 	}
1002 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1003 	pos +=
1004 	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1005 		      data->nrg_silence_ref);
1006 	pos +=
1007 	    scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1008 		      data->nrg_energy_idx);
1009 	pos +=
1010 	    scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1011 		      data->nrg_silence_idx);
1012 	pos +=
1013 	    scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1014 		      data->nrg_th_cck);
1015 	pos +=
1016 	    scnprintf(buf + pos, bufsz - pos,
1017 		      "nrg_auto_corr_silence_diff:\t %u\n",
1018 		      data->nrg_auto_corr_silence_diff);
1019 	pos +=
1020 	    scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1021 		      data->num_in_cck_no_fa);
1022 	pos +=
1023 	    scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1024 		      data->nrg_th_ofdm);
1025 
1026 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1027 	kfree(buf);
1028 	return ret;
1029 }
1030 
1031 static ssize_t
1032 il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
1033 			  size_t count, loff_t *ppos)
1034 {
1035 
1036 	struct il_priv *il = file->private_data;
1037 	int pos = 0;
1038 	int cnt = 0;
1039 	char *buf;
1040 	int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
1041 	ssize_t ret;
1042 	struct il_chain_noise_data *data;
1043 
1044 	data = &il->chain_noise_data;
1045 	buf = kzalloc(bufsz, GFP_KERNEL);
1046 	if (!buf) {
1047 		IL_ERR("Can not allocate Buffer\n");
1048 		return -ENOMEM;
1049 	}
1050 
1051 	pos +=
1052 	    scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1053 		      data->active_chains);
1054 	pos +=
1055 	    scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1056 		      data->chain_noise_a);
1057 	pos +=
1058 	    scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1059 		      data->chain_noise_b);
1060 	pos +=
1061 	    scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1062 		      data->chain_noise_c);
1063 	pos +=
1064 	    scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1065 		      data->chain_signal_a);
1066 	pos +=
1067 	    scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1068 		      data->chain_signal_b);
1069 	pos +=
1070 	    scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1071 		      data->chain_signal_c);
1072 	pos +=
1073 	    scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1074 		      data->beacon_count);
1075 
1076 	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1077 	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1078 		pos +=
1079 		    scnprintf(buf + pos, bufsz - pos, " %u",
1080 			      data->disconn_array[cnt]);
1081 	}
1082 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1083 	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1084 	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1085 		pos +=
1086 		    scnprintf(buf + pos, bufsz - pos, " %u",
1087 			      data->delta_gain_code[cnt]);
1088 	}
1089 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
1090 	pos +=
1091 	    scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1092 		      data->radio_write);
1093 	pos +=
1094 	    scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1095 		      data->state);
1096 
1097 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1098 	kfree(buf);
1099 	return ret;
1100 }
1101 
1102 static ssize_t
1103 il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
1104 				size_t count, loff_t *ppos)
1105 {
1106 	struct il_priv *il = file->private_data;
1107 	char buf[60];
1108 	int pos = 0;
1109 	const size_t bufsz = sizeof(buf);
1110 	u32 pwrsave_status;
1111 
1112 	pwrsave_status =
1113 	    _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
1114 
1115 	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
1116 	pos +=
1117 	    scnprintf(buf + pos, bufsz - pos, "%s\n",
1118 		      (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1119 		      (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1120 		      (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1121 		      "error");
1122 
1123 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1124 }
1125 
1126 static ssize_t
1127 il_dbgfs_clear_ucode_stats_write(struct file *file,
1128 				 const char __user *user_buf, size_t count,
1129 				 loff_t *ppos)
1130 {
1131 	struct il_priv *il = file->private_data;
1132 	char buf[8];
1133 	int buf_size;
1134 	int clear;
1135 
1136 	memset(buf, 0, sizeof(buf));
1137 	buf_size = min(count, sizeof(buf) - 1);
1138 	if (copy_from_user(buf, user_buf, buf_size))
1139 		return -EFAULT;
1140 	if (sscanf(buf, "%d", &clear) != 1)
1141 		return -EFAULT;
1142 
1143 	/* make request to uCode to retrieve stats information */
1144 	mutex_lock(&il->mutex);
1145 	il_send_stats_request(il, CMD_SYNC, true);
1146 	mutex_unlock(&il->mutex);
1147 
1148 	return count;
1149 }
1150 
1151 static ssize_t
1152 il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
1153 			 size_t count, loff_t *ppos)
1154 {
1155 
1156 	struct il_priv *il = file->private_data;
1157 	int len = 0;
1158 	char buf[20];
1159 
1160 	len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags));
1161 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1162 }
1163 
1164 static ssize_t
1165 il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
1166 				size_t count, loff_t *ppos)
1167 {
1168 
1169 	struct il_priv *il = file->private_data;
1170 	int len = 0;
1171 	char buf[20];
1172 
1173 	len =
1174 	    sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
1175 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1176 }
1177 
1178 static ssize_t
1179 il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
1180 		     loff_t *ppos)
1181 {
1182 	struct il_priv *il = file->private_data;
1183 	char *buf;
1184 	int pos = 0;
1185 	ssize_t ret = -EFAULT;
1186 
1187 	if (il->ops->dump_fh) {
1188 		ret = pos = il->ops->dump_fh(il, &buf, true);
1189 		if (buf) {
1190 			ret =
1191 			    simple_read_from_buffer(user_buf, count, ppos, buf,
1192 						    pos);
1193 			kfree(buf);
1194 		}
1195 	}
1196 
1197 	return ret;
1198 }
1199 
1200 static ssize_t
1201 il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
1202 			    size_t count, loff_t *ppos)
1203 {
1204 
1205 	struct il_priv *il = file->private_data;
1206 	int pos = 0;
1207 	char buf[12];
1208 	const size_t bufsz = sizeof(buf);
1209 
1210 	pos +=
1211 	    scnprintf(buf + pos, bufsz - pos, "%d\n",
1212 		      il->missed_beacon_threshold);
1213 
1214 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1215 }
1216 
1217 static ssize_t
1218 il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
1219 			     size_t count, loff_t *ppos)
1220 {
1221 	struct il_priv *il = file->private_data;
1222 	char buf[8];
1223 	int buf_size;
1224 	int missed;
1225 
1226 	memset(buf, 0, sizeof(buf));
1227 	buf_size = min(count, sizeof(buf) - 1);
1228 	if (copy_from_user(buf, user_buf, buf_size))
1229 		return -EFAULT;
1230 	if (sscanf(buf, "%d", &missed) != 1)
1231 		return -EINVAL;
1232 
1233 	if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
1234 	    missed > IL_MISSED_BEACON_THRESHOLD_MAX)
1235 		il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
1236 	else
1237 		il->missed_beacon_threshold = missed;
1238 
1239 	return count;
1240 }
1241 
1242 static ssize_t
1243 il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
1244 			  size_t count, loff_t *ppos)
1245 {
1246 
1247 	struct il_priv *il = file->private_data;
1248 	int pos = 0;
1249 	char buf[300];
1250 	const size_t bufsz = sizeof(buf);
1251 	struct il_force_reset *force_reset;
1252 
1253 	force_reset = &il->force_reset;
1254 
1255 	pos +=
1256 	    scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
1257 		      force_reset->reset_request_count);
1258 	pos +=
1259 	    scnprintf(buf + pos, bufsz - pos,
1260 		      "\tnumber of reset request success: %d\n",
1261 		      force_reset->reset_success_count);
1262 	pos +=
1263 	    scnprintf(buf + pos, bufsz - pos,
1264 		      "\tnumber of reset request reject: %d\n",
1265 		      force_reset->reset_reject_count);
1266 	pos +=
1267 	    scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
1268 		      force_reset->reset_duration);
1269 
1270 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1271 }
1272 
1273 static ssize_t
1274 il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
1275 			   size_t count, loff_t *ppos)
1276 {
1277 
1278 	int ret;
1279 	struct il_priv *il = file->private_data;
1280 
1281 	ret = il_force_reset(il, true);
1282 
1283 	return ret ? ret : count;
1284 }
1285 
1286 static ssize_t
1287 il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
1288 			  size_t count, loff_t *ppos)
1289 {
1290 
1291 	struct il_priv *il = file->private_data;
1292 	char buf[8];
1293 	int buf_size;
1294 	int timeout;
1295 
1296 	memset(buf, 0, sizeof(buf));
1297 	buf_size = min(count, sizeof(buf) - 1);
1298 	if (copy_from_user(buf, user_buf, buf_size))
1299 		return -EFAULT;
1300 	if (sscanf(buf, "%d", &timeout) != 1)
1301 		return -EINVAL;
1302 	if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
1303 		timeout = IL_DEF_WD_TIMEOUT;
1304 
1305 	il->cfg->wd_timeout = timeout;
1306 	il_setup_watchdog(il);
1307 	return count;
1308 }
1309 
1310 DEBUGFS_READ_FILE_OPS(rx_stats);
1311 DEBUGFS_READ_FILE_OPS(tx_stats);
1312 DEBUGFS_READ_FILE_OPS(rx_queue);
1313 DEBUGFS_READ_FILE_OPS(tx_queue);
1314 DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1315 DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1316 DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1317 DEBUGFS_READ_FILE_OPS(sensitivity);
1318 DEBUGFS_READ_FILE_OPS(chain_noise);
1319 DEBUGFS_READ_FILE_OPS(power_save_status);
1320 DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
1321 DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
1322 DEBUGFS_READ_FILE_OPS(fh_reg);
1323 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
1324 DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1325 DEBUGFS_READ_FILE_OPS(rxon_flags);
1326 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1327 DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1328 
1329 /*
1330  * Create the debugfs files and directories
1331  *
1332  */
1333 void
1334 il_dbgfs_register(struct il_priv *il, const char *name)
1335 {
1336 	struct dentry *phyd = il->hw->wiphy->debugfsdir;
1337 	struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1338 
1339 	dir_drv = debugfs_create_dir(name, phyd);
1340 	il->debugfs_dir = dir_drv;
1341 
1342 	dir_data = debugfs_create_dir("data", dir_drv);
1343 	dir_rf = debugfs_create_dir("rf", dir_drv);
1344 	dir_debug = debugfs_create_dir("debug", dir_drv);
1345 
1346 	DEBUGFS_ADD_FILE(nvm, dir_data, 0400);
1347 	DEBUGFS_ADD_FILE(sram, dir_data, 0600);
1348 	DEBUGFS_ADD_FILE(stations, dir_data, 0400);
1349 	DEBUGFS_ADD_FILE(channels, dir_data, 0400);
1350 	DEBUGFS_ADD_FILE(status, dir_data, 0400);
1351 	DEBUGFS_ADD_FILE(interrupt, dir_data, 0600);
1352 	DEBUGFS_ADD_FILE(qos, dir_data, 0400);
1353 	DEBUGFS_ADD_FILE(disable_ht40, dir_data, 0600);
1354 	DEBUGFS_ADD_FILE(rx_stats, dir_debug, 0400);
1355 	DEBUGFS_ADD_FILE(tx_stats, dir_debug, 0400);
1356 	DEBUGFS_ADD_FILE(rx_queue, dir_debug, 0400);
1357 	DEBUGFS_ADD_FILE(tx_queue, dir_debug, 0400);
1358 	DEBUGFS_ADD_FILE(power_save_status, dir_debug, 0400);
1359 	DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, 0200);
1360 	DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, 0200);
1361 	DEBUGFS_ADD_FILE(fh_reg, dir_debug, 0400);
1362 	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, 0200);
1363 	DEBUGFS_ADD_FILE(force_reset, dir_debug, 0600);
1364 	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, 0400);
1365 	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, 0400);
1366 	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, 0400);
1367 
1368 	if (il->cfg->sensitivity_calib_by_driver)
1369 		DEBUGFS_ADD_FILE(sensitivity, dir_debug, 0400);
1370 	if (il->cfg->chain_noise_calib_by_driver)
1371 		DEBUGFS_ADD_FILE(chain_noise, dir_debug, 0400);
1372 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, 0200);
1373 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, 0200);
1374 	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, 0200);
1375 	if (il->cfg->sensitivity_calib_by_driver)
1376 		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
1377 				 &il->disable_sens_cal);
1378 	if (il->cfg->chain_noise_calib_by_driver)
1379 		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
1380 				 &il->disable_chain_noise_cal);
1381 	DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
1382 }
1383 EXPORT_SYMBOL(il_dbgfs_register);
1384 
1385 /**
1386  * Remove the debugfs files and directories
1387  *
1388  */
1389 void
1390 il_dbgfs_unregister(struct il_priv *il)
1391 {
1392 	if (!il->debugfs_dir)
1393 		return;
1394 
1395 	debugfs_remove_recursive(il->debugfs_dir);
1396 	il->debugfs_dir = NULL;
1397 }
1398 EXPORT_SYMBOL(il_dbgfs_unregister);
1399