Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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 ", ofs);
519                 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, buf + pos,
520                                    buf_size - pos, 0);
521                 pos += strlen(buf + pos);
522                 if (buf_size - pos > 0)
523                         buf[pos++] = '\n';
524         }
525
526         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
527         kfree(buf);
528         return ret;
529 }
530
531 static ssize_t
532 il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
533                        loff_t *ppos)
534 {
535         struct il_priv *il = file->private_data;
536         struct ieee80211_channel *channels = NULL;
537         const struct ieee80211_supported_band *supp_band = NULL;
538         int pos = 0, i, bufsz = PAGE_SIZE;
539         char *buf;
540         ssize_t ret;
541
542         if (!test_bit(S_GEO_CONFIGURED, &il->status))
543                 return -EAGAIN;
544
545         buf = kzalloc(bufsz, GFP_KERNEL);
546         if (!buf) {
547                 IL_ERR("Can not allocate Buffer\n");
548                 return -ENOMEM;
549         }
550
551         supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ);
552         if (supp_band) {
553                 channels = supp_band->channels;
554
555                 pos +=
556                     scnprintf(buf + pos, bufsz - pos,
557                               "Displaying %d channels in 2.4GHz band 802.11bg):\n",
558                               supp_band->n_channels);
559
560                 for (i = 0; i < supp_band->n_channels; i++)
561                         pos +=
562                             scnprintf(buf + pos, bufsz - pos,
563                                       "%d: %ddBm: BSS%s%s, %s.\n",
564                                       channels[i].hw_value,
565                                       channels[i].max_power,
566                                       channels[i].
567                                       flags & IEEE80211_CHAN_RADAR ?
568                                       " (IEEE 802.11h required)" : "",
569                                       ((channels[i].
570                                         flags & IEEE80211_CHAN_NO_IR) ||
571                                        (channels[i].
572                                         flags & IEEE80211_CHAN_RADAR)) ? "" :
573                                       ", IBSS",
574                                       channels[i].
575                                       flags & IEEE80211_CHAN_NO_IR ?
576                                       "passive only" : "active/passive");
577         }
578         supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
579         if (supp_band) {
580                 channels = supp_band->channels;
581
582                 pos +=
583                     scnprintf(buf + pos, bufsz - pos,
584                               "Displaying %d channels in 5.2GHz band (802.11a)\n",
585                               supp_band->n_channels);
586
587                 for (i = 0; i < supp_band->n_channels; i++)
588                         pos +=
589                             scnprintf(buf + pos, bufsz - pos,
590                                       "%d: %ddBm: BSS%s%s, %s.\n",
591                                       channels[i].hw_value,
592                                       channels[i].max_power,
593                                       channels[i].
594                                       flags & IEEE80211_CHAN_RADAR ?
595                                       " (IEEE 802.11h required)" : "",
596                                       ((channels[i].
597                                         flags & IEEE80211_CHAN_NO_IR) ||
598                                        (channels[i].
599                                         flags & IEEE80211_CHAN_RADAR)) ? "" :
600                                       ", IBSS",
601                                       channels[i].
602                                       flags & IEEE80211_CHAN_NO_IR ?
603                                       "passive only" : "active/passive");
604         }
605         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
606         kfree(buf);
607         return ret;
608 }
609
610 static ssize_t
611 il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
612                      loff_t *ppos)
613 {
614
615         struct il_priv *il = file->private_data;
616         char buf[512];
617         int pos = 0;
618         const size_t bufsz = sizeof(buf);
619
620         pos +=
621             scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n",
622                       test_bit(S_HCMD_ACTIVE, &il->status));
623         pos +=
624             scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n",
625                       test_bit(S_INT_ENABLED, &il->status));
626         pos +=
627             scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n",
628                       test_bit(S_RFKILL, &il->status));
629         pos +=
630             scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n",
631                       test_bit(S_CT_KILL, &il->status));
632         pos +=
633             scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n",
634                       test_bit(S_INIT, &il->status));
635         pos +=
636             scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n",
637                       test_bit(S_ALIVE, &il->status));
638         pos +=
639             scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n",
640                       test_bit(S_READY, &il->status));
641         pos +=
642             scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n",
643                       test_bit(S_TEMPERATURE, &il->status));
644         pos +=
645             scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n",
646                       test_bit(S_GEO_CONFIGURED, &il->status));
647         pos +=
648             scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n",
649                       test_bit(S_EXIT_PENDING, &il->status));
650         pos +=
651             scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n",
652                       test_bit(S_STATS, &il->status));
653         pos +=
654             scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n",
655                       test_bit(S_SCANNING, &il->status));
656         pos +=
657             scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n",
658                       test_bit(S_SCAN_ABORTING, &il->status));
659         pos +=
660             scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n",
661                       test_bit(S_SCAN_HW, &il->status));
662         pos +=
663             scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n",
664                       test_bit(S_POWER_PMI, &il->status));
665         pos +=
666             scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n",
667                       test_bit(S_FW_ERROR, &il->status));
668         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
669 }
670
671 static ssize_t
672 il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
673                         loff_t *ppos)
674 {
675
676         struct il_priv *il = file->private_data;
677         int pos = 0;
678         int cnt = 0;
679         char *buf;
680         int bufsz = 24 * 64;    /* 24 items * 64 char per item */
681         ssize_t ret;
682
683         buf = kzalloc(bufsz, GFP_KERNEL);
684         if (!buf) {
685                 IL_ERR("Can not allocate Buffer\n");
686                 return -ENOMEM;
687         }
688
689         pos +=
690             scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
691
692         pos +=
693             scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
694                       il->isr_stats.hw);
695         pos +=
696             scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
697                       il->isr_stats.sw);
698         if (il->isr_stats.sw || il->isr_stats.hw) {
699                 pos +=
700                     scnprintf(buf + pos, bufsz - pos,
701                               "\tLast Restarting Code:  0x%X\n",
702                               il->isr_stats.err_code);
703         }
704 #ifdef CONFIG_IWLEGACY_DEBUG
705         pos +=
706             scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
707                       il->isr_stats.sch);
708         pos +=
709             scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
710                       il->isr_stats.alive);
711 #endif
712         pos +=
713             scnprintf(buf + pos, bufsz - pos,
714                       "HW RF KILL switch toggled:\t %u\n",
715                       il->isr_stats.rfkill);
716
717         pos +=
718             scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
719                       il->isr_stats.ctkill);
720
721         pos +=
722             scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
723                       il->isr_stats.wakeup);
724
725         pos +=
726             scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n",
727                       il->isr_stats.rx);
728         for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
729                 if (il->isr_stats.handlers[cnt] > 0)
730                         pos +=
731                             scnprintf(buf + pos, bufsz - pos,
732                                       "\tRx handler[%36s]:\t\t %u\n",
733                                       il_get_cmd_string(cnt),
734                                       il->isr_stats.handlers[cnt]);
735         }
736
737         pos +=
738             scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
739                       il->isr_stats.tx);
740
741         pos +=
742             scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
743                       il->isr_stats.unhandled);
744
745         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
746         kfree(buf);
747         return ret;
748 }
749
750 static ssize_t
751 il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
752                          size_t count, loff_t *ppos)
753 {
754         struct il_priv *il = file->private_data;
755         char buf[8];
756         int buf_size;
757         u32 reset_flag;
758
759         memset(buf, 0, sizeof(buf));
760         buf_size = min(count, sizeof(buf) - 1);
761         if (copy_from_user(buf, user_buf, buf_size))
762                 return -EFAULT;
763         if (sscanf(buf, "%x", &reset_flag) != 1)
764                 return -EFAULT;
765         if (reset_flag == 0)
766                 il_clear_isr_stats(il);
767
768         return count;
769 }
770
771 static ssize_t
772 il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
773                   loff_t *ppos)
774 {
775         struct il_priv *il = file->private_data;
776         int pos = 0, i;
777         char buf[256];
778         const size_t bufsz = sizeof(buf);
779
780         for (i = 0; i < AC_NUM; i++) {
781                 pos +=
782                     scnprintf(buf + pos, bufsz - pos,
783                               "\tcw_min\tcw_max\taifsn\ttxop\n");
784                 pos +=
785                     scnprintf(buf + pos, bufsz - pos,
786                               "AC[%d]\t%u\t%u\t%u\t%u\n", i,
787                               il->qos_data.def_qos_parm.ac[i].cw_min,
788                               il->qos_data.def_qos_parm.ac[i].cw_max,
789                               il->qos_data.def_qos_parm.ac[i].aifsn,
790                               il->qos_data.def_qos_parm.ac[i].edca_txop);
791         }
792
793         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
794 }
795
796 static ssize_t
797 il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
798                             size_t count, loff_t *ppos)
799 {
800         struct il_priv *il = file->private_data;
801         char buf[8];
802         int buf_size;
803         int ht40;
804
805         memset(buf, 0, sizeof(buf));
806         buf_size = min(count, sizeof(buf) - 1);
807         if (copy_from_user(buf, user_buf, buf_size))
808                 return -EFAULT;
809         if (sscanf(buf, "%d", &ht40) != 1)
810                 return -EFAULT;
811         if (!il_is_any_associated(il))
812                 il->disable_ht40 = ht40 ? true : false;
813         else {
814                 IL_ERR("Sta associated with AP - "
815                        "Change to 40MHz channel support is not allowed\n");
816                 return -EINVAL;
817         }
818
819         return count;
820 }
821
822 static ssize_t
823 il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
824                            size_t count, loff_t *ppos)
825 {
826         struct il_priv *il = file->private_data;
827         char buf[100];
828         int pos = 0;
829         const size_t bufsz = sizeof(buf);
830
831         pos +=
832             scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
833                       il->disable_ht40 ? "Disabled" : "Enabled");
834         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
835 }
836
837 DEBUGFS_READ_WRITE_FILE_OPS(sram);
838 DEBUGFS_READ_FILE_OPS(nvm);
839 DEBUGFS_READ_FILE_OPS(stations);
840 DEBUGFS_READ_FILE_OPS(channels);
841 DEBUGFS_READ_FILE_OPS(status);
842 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
843 DEBUGFS_READ_FILE_OPS(qos);
844 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
845
846 static ssize_t
847 il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
848                        loff_t *ppos)
849 {
850
851         struct il_priv *il = file->private_data;
852         struct il_tx_queue *txq;
853         struct il_queue *q;
854         char *buf;
855         int pos = 0;
856         int cnt;
857         int ret;
858         const size_t bufsz =
859             sizeof(char) * 64 * il->cfg->num_of_queues;
860
861         if (!il->txq) {
862                 IL_ERR("txq not ready\n");
863                 return -EAGAIN;
864         }
865         buf = kzalloc(bufsz, GFP_KERNEL);
866         if (!buf)
867                 return -ENOMEM;
868
869         for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
870                 txq = &il->txq[cnt];
871                 q = &txq->q;
872                 pos +=
873                     scnprintf(buf + pos, bufsz - pos,
874                               "hwq %.2d: read=%u write=%u stop=%d"
875                               " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
876                               q->read_ptr, q->write_ptr,
877                               !!test_bit(cnt, il->queue_stopped),
878                               txq->swq_id, txq->swq_id & 3,
879                               (txq->swq_id >> 2) & 0x1f);
880                 if (cnt >= 4)
881                         continue;
882                 /* for the ACs, display the stop count too */
883                 pos +=
884                     scnprintf(buf + pos, bufsz - pos,
885                               "        stop-count: %d\n",
886                               atomic_read(&il->queue_stop_count[cnt]));
887         }
888         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
889         kfree(buf);
890         return ret;
891 }
892
893 static ssize_t
894 il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
895                        loff_t *ppos)
896 {
897
898         struct il_priv *il = file->private_data;
899         struct il_rx_queue *rxq = &il->rxq;
900         char buf[256];
901         int pos = 0;
902         const size_t bufsz = sizeof(buf);
903
904         pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
905         pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
906         pos +=
907             scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
908                       rxq->free_count);
909         if (rxq->rb_stts) {
910                 pos +=
911                     scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
912                               le16_to_cpu(rxq->rb_stts->
913                                           closed_rb_num) & 0x0FFF);
914         } else {
915                 pos +=
916                     scnprintf(buf + pos, bufsz - pos,
917                               "closed_rb_num: Not Allocated\n");
918         }
919         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
920 }
921
922 static ssize_t
923 il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
924                              size_t count, loff_t *ppos)
925 {
926         struct il_priv *il = file->private_data;
927
928         return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos);
929 }
930
931 static ssize_t
932 il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
933                              size_t count, loff_t *ppos)
934 {
935         struct il_priv *il = file->private_data;
936
937         return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos);
938 }
939
940 static ssize_t
941 il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
942                                   size_t count, loff_t *ppos)
943 {
944         struct il_priv *il = file->private_data;
945
946         return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos);
947 }
948
949 static ssize_t
950 il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
951                           size_t count, loff_t *ppos)
952 {
953
954         struct il_priv *il = file->private_data;
955         int pos = 0;
956         int cnt = 0;
957         char *buf;
958         int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
959         ssize_t ret;
960         struct il_sensitivity_data *data;
961
962         data = &il->sensitivity_data;
963         buf = kzalloc(bufsz, GFP_KERNEL);
964         if (!buf) {
965                 IL_ERR("Can not allocate Buffer\n");
966                 return -ENOMEM;
967         }
968
969         pos +=
970             scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
971                       data->auto_corr_ofdm);
972         pos +=
973             scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
974                       data->auto_corr_ofdm_mrc);
975         pos +=
976             scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
977                       data->auto_corr_ofdm_x1);
978         pos +=
979             scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
980                       data->auto_corr_ofdm_mrc_x1);
981         pos +=
982             scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
983                       data->auto_corr_cck);
984         pos +=
985             scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
986                       data->auto_corr_cck_mrc);
987         pos +=
988             scnprintf(buf + pos, bufsz - pos,
989                       "last_bad_plcp_cnt_ofdm:\t\t %u\n",
990                       data->last_bad_plcp_cnt_ofdm);
991         pos +=
992             scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
993                       data->last_fa_cnt_ofdm);
994         pos +=
995             scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
996                       data->last_bad_plcp_cnt_cck);
997         pos +=
998             scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
999                       data->last_fa_cnt_cck);
1000         pos +=
1001             scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
1002                       data->nrg_curr_state);
1003         pos +=
1004             scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
1005                       data->nrg_prev_state);
1006         pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
1007         for (cnt = 0; cnt < 10; cnt++) {
1008                 pos +=
1009                     scnprintf(buf + pos, bufsz - pos, " %u",
1010                               data->nrg_value[cnt]);
1011         }
1012         pos += scnprintf(buf + pos, bufsz - pos, "\n");
1013         pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
1014         for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
1015                 pos +=
1016                     scnprintf(buf + pos, bufsz - pos, " %u",
1017                               data->nrg_silence_rssi[cnt]);
1018         }
1019         pos += scnprintf(buf + pos, bufsz - pos, "\n");
1020         pos +=
1021             scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1022                       data->nrg_silence_ref);
1023         pos +=
1024             scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1025                       data->nrg_energy_idx);
1026         pos +=
1027             scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1028                       data->nrg_silence_idx);
1029         pos +=
1030             scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1031                       data->nrg_th_cck);
1032         pos +=
1033             scnprintf(buf + pos, bufsz - pos,
1034                       "nrg_auto_corr_silence_diff:\t %u\n",
1035                       data->nrg_auto_corr_silence_diff);
1036         pos +=
1037             scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1038                       data->num_in_cck_no_fa);
1039         pos +=
1040             scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1041                       data->nrg_th_ofdm);
1042
1043         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1044         kfree(buf);
1045         return ret;
1046 }
1047
1048 static ssize_t
1049 il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
1050                           size_t count, loff_t *ppos)
1051 {
1052
1053         struct il_priv *il = file->private_data;
1054         int pos = 0;
1055         int cnt = 0;
1056         char *buf;
1057         int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
1058         ssize_t ret;
1059         struct il_chain_noise_data *data;
1060
1061         data = &il->chain_noise_data;
1062         buf = kzalloc(bufsz, GFP_KERNEL);
1063         if (!buf) {
1064                 IL_ERR("Can not allocate Buffer\n");
1065                 return -ENOMEM;
1066         }
1067
1068         pos +=
1069             scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1070                       data->active_chains);
1071         pos +=
1072             scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1073                       data->chain_noise_a);
1074         pos +=
1075             scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1076                       data->chain_noise_b);
1077         pos +=
1078             scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1079                       data->chain_noise_c);
1080         pos +=
1081             scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1082                       data->chain_signal_a);
1083         pos +=
1084             scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1085                       data->chain_signal_b);
1086         pos +=
1087             scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1088                       data->chain_signal_c);
1089         pos +=
1090             scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1091                       data->beacon_count);
1092
1093         pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1094         for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1095                 pos +=
1096                     scnprintf(buf + pos, bufsz - pos, " %u",
1097                               data->disconn_array[cnt]);
1098         }
1099         pos += scnprintf(buf + pos, bufsz - pos, "\n");
1100         pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1101         for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1102                 pos +=
1103                     scnprintf(buf + pos, bufsz - pos, " %u",
1104                               data->delta_gain_code[cnt]);
1105         }
1106         pos += scnprintf(buf + pos, bufsz - pos, "\n");
1107         pos +=
1108             scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1109                       data->radio_write);
1110         pos +=
1111             scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1112                       data->state);
1113
1114         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1115         kfree(buf);
1116         return ret;
1117 }
1118
1119 static ssize_t
1120 il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
1121                                 size_t count, loff_t *ppos)
1122 {
1123         struct il_priv *il = file->private_data;
1124         char buf[60];
1125         int pos = 0;
1126         const size_t bufsz = sizeof(buf);
1127         u32 pwrsave_status;
1128
1129         pwrsave_status =
1130             _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
1131
1132         pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
1133         pos +=
1134             scnprintf(buf + pos, bufsz - pos, "%s\n",
1135                       (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1136                       (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1137                       (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1138                       "error");
1139
1140         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1141 }
1142
1143 static ssize_t
1144 il_dbgfs_clear_ucode_stats_write(struct file *file,
1145                                  const char __user *user_buf, size_t count,
1146                                  loff_t *ppos)
1147 {
1148         struct il_priv *il = file->private_data;
1149         char buf[8];
1150         int buf_size;
1151         int clear;
1152
1153         memset(buf, 0, sizeof(buf));
1154         buf_size = min(count, sizeof(buf) - 1);
1155         if (copy_from_user(buf, user_buf, buf_size))
1156                 return -EFAULT;
1157         if (sscanf(buf, "%d", &clear) != 1)
1158                 return -EFAULT;
1159
1160         /* make request to uCode to retrieve stats information */
1161         mutex_lock(&il->mutex);
1162         il_send_stats_request(il, CMD_SYNC, true);
1163         mutex_unlock(&il->mutex);
1164
1165         return count;
1166 }
1167
1168 static ssize_t
1169 il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
1170                          size_t count, loff_t *ppos)
1171 {
1172
1173         struct il_priv *il = file->private_data;
1174         int len = 0;
1175         char buf[20];
1176
1177         len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags));
1178         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1179 }
1180
1181 static ssize_t
1182 il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
1183                                 size_t count, loff_t *ppos)
1184 {
1185
1186         struct il_priv *il = file->private_data;
1187         int len = 0;
1188         char buf[20];
1189
1190         len =
1191             sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
1192         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1193 }
1194
1195 static ssize_t
1196 il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
1197                      loff_t *ppos)
1198 {
1199         struct il_priv *il = file->private_data;
1200         char *buf;
1201         int pos = 0;
1202         ssize_t ret = -EFAULT;
1203
1204         if (il->ops->dump_fh) {
1205                 ret = pos = il->ops->dump_fh(il, &buf, true);
1206                 if (buf) {
1207                         ret =
1208                             simple_read_from_buffer(user_buf, count, ppos, buf,
1209                                                     pos);
1210                         kfree(buf);
1211                 }
1212         }
1213
1214         return ret;
1215 }
1216
1217 static ssize_t
1218 il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
1219                             size_t count, loff_t *ppos)
1220 {
1221
1222         struct il_priv *il = file->private_data;
1223         int pos = 0;
1224         char buf[12];
1225         const size_t bufsz = sizeof(buf);
1226
1227         pos +=
1228             scnprintf(buf + pos, bufsz - pos, "%d\n",
1229                       il->missed_beacon_threshold);
1230
1231         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1232 }
1233
1234 static ssize_t
1235 il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
1236                              size_t count, loff_t *ppos)
1237 {
1238         struct il_priv *il = file->private_data;
1239         char buf[8];
1240         int buf_size;
1241         int missed;
1242
1243         memset(buf, 0, sizeof(buf));
1244         buf_size = min(count, sizeof(buf) - 1);
1245         if (copy_from_user(buf, user_buf, buf_size))
1246                 return -EFAULT;
1247         if (sscanf(buf, "%d", &missed) != 1)
1248                 return -EINVAL;
1249
1250         if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
1251             missed > IL_MISSED_BEACON_THRESHOLD_MAX)
1252                 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
1253         else
1254                 il->missed_beacon_threshold = missed;
1255
1256         return count;
1257 }
1258
1259 static ssize_t
1260 il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
1261                           size_t count, loff_t *ppos)
1262 {
1263
1264         struct il_priv *il = file->private_data;
1265         int pos = 0;
1266         char buf[300];
1267         const size_t bufsz = sizeof(buf);
1268         struct il_force_reset *force_reset;
1269
1270         force_reset = &il->force_reset;
1271
1272         pos +=
1273             scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
1274                       force_reset->reset_request_count);
1275         pos +=
1276             scnprintf(buf + pos, bufsz - pos,
1277                       "\tnumber of reset request success: %d\n",
1278                       force_reset->reset_success_count);
1279         pos +=
1280             scnprintf(buf + pos, bufsz - pos,
1281                       "\tnumber of reset request reject: %d\n",
1282                       force_reset->reset_reject_count);
1283         pos +=
1284             scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
1285                       force_reset->reset_duration);
1286
1287         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1288 }
1289
1290 static ssize_t
1291 il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
1292                            size_t count, loff_t *ppos)
1293 {
1294
1295         int ret;
1296         struct il_priv *il = file->private_data;
1297
1298         ret = il_force_reset(il, true);
1299
1300         return ret ? ret : count;
1301 }
1302
1303 static ssize_t
1304 il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
1305                           size_t count, loff_t *ppos)
1306 {
1307
1308         struct il_priv *il = file->private_data;
1309         char buf[8];
1310         int buf_size;
1311         int timeout;
1312
1313         memset(buf, 0, sizeof(buf));
1314         buf_size = min(count, sizeof(buf) - 1);
1315         if (copy_from_user(buf, user_buf, buf_size))
1316                 return -EFAULT;
1317         if (sscanf(buf, "%d", &timeout) != 1)
1318                 return -EINVAL;
1319         if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
1320                 timeout = IL_DEF_WD_TIMEOUT;
1321
1322         il->cfg->wd_timeout = timeout;
1323         il_setup_watchdog(il);
1324         return count;
1325 }
1326
1327 DEBUGFS_READ_FILE_OPS(rx_stats);
1328 DEBUGFS_READ_FILE_OPS(tx_stats);
1329 DEBUGFS_READ_FILE_OPS(rx_queue);
1330 DEBUGFS_READ_FILE_OPS(tx_queue);
1331 DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1332 DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1333 DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1334 DEBUGFS_READ_FILE_OPS(sensitivity);
1335 DEBUGFS_READ_FILE_OPS(chain_noise);
1336 DEBUGFS_READ_FILE_OPS(power_save_status);
1337 DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
1338 DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
1339 DEBUGFS_READ_FILE_OPS(fh_reg);
1340 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
1341 DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1342 DEBUGFS_READ_FILE_OPS(rxon_flags);
1343 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1344 DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1345
1346 /*
1347  * Create the debugfs files and directories
1348  *
1349  */
1350 int
1351 il_dbgfs_register(struct il_priv *il, const char *name)
1352 {
1353         struct dentry *phyd = il->hw->wiphy->debugfsdir;
1354         struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1355
1356         dir_drv = debugfs_create_dir(name, phyd);
1357         if (!dir_drv)
1358                 return -ENOMEM;
1359
1360         il->debugfs_dir = dir_drv;
1361
1362         dir_data = debugfs_create_dir("data", dir_drv);
1363         if (!dir_data)
1364                 goto err;
1365         dir_rf = debugfs_create_dir("rf", dir_drv);
1366         if (!dir_rf)
1367                 goto err;
1368         dir_debug = debugfs_create_dir("debug", dir_drv);
1369         if (!dir_debug)
1370                 goto err;
1371
1372         DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
1373         DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
1374         DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
1375         DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
1376         DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1377         DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1378         DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1379         DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
1380         DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR);
1381         DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR);
1382         DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
1383         DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
1384         DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
1385         DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR);
1386         DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR);
1387         DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
1388         DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
1389         DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
1390         DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
1391         DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
1392         DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
1393
1394         if (il->cfg->sensitivity_calib_by_driver)
1395                 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
1396         if (il->cfg->chain_noise_calib_by_driver)
1397                 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
1398         DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
1399         DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
1400         DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
1401         if (il->cfg->sensitivity_calib_by_driver)
1402                 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
1403                                  &il->disable_sens_cal);
1404         if (il->cfg->chain_noise_calib_by_driver)
1405                 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
1406                                  &il->disable_chain_noise_cal);
1407         DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
1408         return 0;
1409
1410 err:
1411         IL_ERR("Can't create the debugfs directory\n");
1412         il_dbgfs_unregister(il);
1413         return -ENOMEM;
1414 }
1415 EXPORT_SYMBOL(il_dbgfs_register);
1416
1417 /**
1418  * Remove the debugfs files and directories
1419  *
1420  */
1421 void
1422 il_dbgfs_unregister(struct il_priv *il)
1423 {
1424         if (!il->debugfs_dir)
1425                 return;
1426
1427         debugfs_remove_recursive(il->debugfs_dir);
1428         il->debugfs_dir = NULL;
1429 }
1430 EXPORT_SYMBOL(il_dbgfs_unregister);