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