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