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