]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/net/wireless/iwlegacy/debug.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / iwlegacy / debug.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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);