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