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