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