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