iwlagn: hw_params moves to iwl_shared
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-debugfs.c
1 /******************************************************************************
2  *
3  * GPL LICENSE SUMMARY
4  *
5  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19  * USA
20  *
21  * The full GNU General Public License is included in this distribution
22  * in the file called LICENSE.GPL.
23  *
24  * Contact Information:
25  *  Intel Linux Wireless <ilw@linux.intel.com>
26  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27  *****************************************************************************/
28
29 #include <linux/slab.h>
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/debugfs.h>
33
34 #include <linux/ieee80211.h>
35 #include <net/mac80211.h>
36
37
38 #include "iwl-dev.h"
39 #include "iwl-debug.h"
40 #include "iwl-core.h"
41 #include "iwl-io.h"
42 #include "iwl-agn.h"
43
44 /* create and remove of files */
45 #define DEBUGFS_ADD_FILE(name, parent, mode) do {                       \
46         if (!debugfs_create_file(#name, mode, parent, priv,             \
47                                  &iwl_dbgfs_##name##_ops))              \
48                 goto err;                                               \
49 } while (0)
50
51 #define DEBUGFS_ADD_BOOL(name, parent, ptr) do {                        \
52         struct dentry *__tmp;                                           \
53         __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,           \
54                                     parent, ptr);                       \
55         if (IS_ERR(__tmp) || !__tmp)                                    \
56                 goto err;                                               \
57 } while (0)
58
59 #define DEBUGFS_ADD_X32(name, parent, ptr) do {                         \
60         struct dentry *__tmp;                                           \
61         __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,            \
62                                    parent, ptr);                        \
63         if (IS_ERR(__tmp) || !__tmp)                                    \
64                 goto err;                                               \
65 } while (0)
66
67 /* file operation */
68 #define DEBUGFS_READ_FUNC(name)                                         \
69 static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
70                                         char __user *user_buf,          \
71                                         size_t count, loff_t *ppos);
72
73 #define DEBUGFS_WRITE_FUNC(name)                                        \
74 static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
75                                         const char __user *user_buf,    \
76                                         size_t count, loff_t *ppos);
77
78
79 static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
80 {
81         file->private_data = inode->i_private;
82         return 0;
83 }
84
85 #define DEBUGFS_READ_FILE_OPS(name)                                     \
86         DEBUGFS_READ_FUNC(name);                                        \
87 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
88         .read = iwl_dbgfs_##name##_read,                                \
89         .open = iwl_dbgfs_open_file_generic,                            \
90         .llseek = generic_file_llseek,                                  \
91 };
92
93 #define DEBUGFS_WRITE_FILE_OPS(name)                                    \
94         DEBUGFS_WRITE_FUNC(name);                                       \
95 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
96         .write = iwl_dbgfs_##name##_write,                              \
97         .open = iwl_dbgfs_open_file_generic,                            \
98         .llseek = generic_file_llseek,                                  \
99 };
100
101
102 #define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \
103         DEBUGFS_READ_FUNC(name);                                        \
104         DEBUGFS_WRITE_FUNC(name);                                       \
105 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
106         .write = iwl_dbgfs_##name##_write,                              \
107         .read = iwl_dbgfs_##name##_read,                                \
108         .open = iwl_dbgfs_open_file_generic,                            \
109         .llseek = generic_file_llseek,                                  \
110 };
111
112 static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
113                                                 char __user *user_buf,
114                                                 size_t count, loff_t *ppos) {
115
116         struct iwl_priv *priv = file->private_data;
117         char *buf;
118         int pos = 0;
119
120         int cnt;
121         ssize_t ret;
122         const size_t bufsz = 100 +
123                 sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
124         buf = kzalloc(bufsz, GFP_KERNEL);
125         if (!buf)
126                 return -ENOMEM;
127         pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
128         for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
129                 pos += scnprintf(buf + pos, bufsz - pos,
130                                  "\t%25s\t\t: %u\n",
131                                  get_mgmt_string(cnt),
132                                  priv->tx_stats.mgmt[cnt]);
133         }
134         pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
135         for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
136                 pos += scnprintf(buf + pos, bufsz - pos,
137                                  "\t%25s\t\t: %u\n",
138                                  get_ctrl_string(cnt),
139                                  priv->tx_stats.ctrl[cnt]);
140         }
141         pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
142         pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
143                          priv->tx_stats.data_cnt);
144         pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
145                          priv->tx_stats.data_bytes);
146         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
147         kfree(buf);
148         return ret;
149 }
150
151 static ssize_t iwl_dbgfs_clear_traffic_statistics_write(struct file *file,
152                                         const char __user *user_buf,
153                                         size_t count, loff_t *ppos)
154 {
155         struct iwl_priv *priv = file->private_data;
156         u32 clear_flag;
157         char buf[8];
158         int buf_size;
159
160         memset(buf, 0, sizeof(buf));
161         buf_size = min(count, sizeof(buf) -  1);
162         if (copy_from_user(buf, user_buf, buf_size))
163                 return -EFAULT;
164         if (sscanf(buf, "%x", &clear_flag) != 1)
165                 return -EFAULT;
166         iwl_clear_traffic_stats(priv);
167
168         return count;
169 }
170
171 static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
172                                                 char __user *user_buf,
173                                                 size_t count, loff_t *ppos) {
174
175         struct iwl_priv *priv = file->private_data;
176         char *buf;
177         int pos = 0;
178         int cnt;
179         ssize_t ret;
180         const size_t bufsz = 100 +
181                 sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
182         buf = kzalloc(bufsz, GFP_KERNEL);
183         if (!buf)
184                 return -ENOMEM;
185
186         pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
187         for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
188                 pos += scnprintf(buf + pos, bufsz - pos,
189                                  "\t%25s\t\t: %u\n",
190                                  get_mgmt_string(cnt),
191                                  priv->rx_stats.mgmt[cnt]);
192         }
193         pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
194         for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
195                 pos += scnprintf(buf + pos, bufsz - pos,
196                                  "\t%25s\t\t: %u\n",
197                                  get_ctrl_string(cnt),
198                                  priv->rx_stats.ctrl[cnt]);
199         }
200         pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
201         pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
202                          priv->rx_stats.data_cnt);
203         pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
204                          priv->rx_stats.data_bytes);
205
206         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
207         kfree(buf);
208         return ret;
209 }
210
211 static ssize_t iwl_dbgfs_sram_read(struct file *file,
212                                         char __user *user_buf,
213                                         size_t count, loff_t *ppos)
214 {
215         u32 val = 0;
216         char *buf;
217         ssize_t ret;
218         int i = 0;
219         bool device_format = false;
220         int offset = 0;
221         int len = 0;
222         int pos = 0;
223         int sram;
224         struct iwl_priv *priv = file->private_data;
225         size_t bufsz;
226
227         /* default is to dump the entire data segment */
228         if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
229                 priv->dbgfs_sram_offset = 0x800000;
230                 if (priv->ucode_type == IWL_UCODE_INIT)
231                         priv->dbgfs_sram_len = priv->ucode_init.data.len;
232                 else
233                         priv->dbgfs_sram_len = priv->ucode_rt.data.len;
234         }
235         len = priv->dbgfs_sram_len;
236
237         if (len == -4) {
238                 device_format = true;
239                 len = 4;
240         }
241
242         bufsz =  50 + len * 4;
243         buf = kmalloc(bufsz, GFP_KERNEL);
244         if (!buf)
245                 return -ENOMEM;
246
247         pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
248                          len);
249         pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
250                         priv->dbgfs_sram_offset);
251
252         /* adjust sram address since reads are only on even u32 boundaries */
253         offset = priv->dbgfs_sram_offset & 0x3;
254         sram = priv->dbgfs_sram_offset & ~0x3;
255
256         /* read the first u32 from sram */
257         val = iwl_read_targ_mem(priv, sram);
258
259         for (; len; len--) {
260                 /* put the address at the start of every line */
261                 if (i == 0)
262                         pos += scnprintf(buf + pos, bufsz - pos,
263                                 "%08X: ", sram + offset);
264
265                 if (device_format)
266                         pos += scnprintf(buf + pos, bufsz - pos,
267                                 "%02x", (val >> (8 * (3 - offset))) & 0xff);
268                 else
269                         pos += scnprintf(buf + pos, bufsz - pos,
270                                 "%02x ", (val >> (8 * offset)) & 0xff);
271
272                 /* if all bytes processed, read the next u32 from sram */
273                 if (++offset == 4) {
274                         sram += 4;
275                         offset = 0;
276                         val = iwl_read_targ_mem(priv, sram);
277                 }
278
279                 /* put in extra spaces and split lines for human readability */
280                 if (++i == 16) {
281                         i = 0;
282                         pos += scnprintf(buf + pos, bufsz - pos, "\n");
283                 } else if (!(i & 7)) {
284                         pos += scnprintf(buf + pos, bufsz - pos, "   ");
285                 } else if (!(i & 3)) {
286                         pos += scnprintf(buf + pos, bufsz - pos, " ");
287                 }
288         }
289         if (i)
290                 pos += scnprintf(buf + pos, bufsz - pos, "\n");
291
292         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
293         kfree(buf);
294         return ret;
295 }
296
297 static ssize_t iwl_dbgfs_sram_write(struct file *file,
298                                         const char __user *user_buf,
299                                         size_t count, loff_t *ppos)
300 {
301         struct iwl_priv *priv = file->private_data;
302         char buf[64];
303         int buf_size;
304         u32 offset, len;
305
306         memset(buf, 0, sizeof(buf));
307         buf_size = min(count, sizeof(buf) -  1);
308         if (copy_from_user(buf, user_buf, buf_size))
309                 return -EFAULT;
310
311         if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
312                 priv->dbgfs_sram_offset = offset;
313                 priv->dbgfs_sram_len = len;
314         } else if (sscanf(buf, "%x", &offset) == 1) {
315                 priv->dbgfs_sram_offset = offset;
316                 priv->dbgfs_sram_len = -4;
317         } else {
318                 priv->dbgfs_sram_offset = 0;
319                 priv->dbgfs_sram_len = 0;
320         }
321
322         return count;
323 }
324
325 static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
326                                           char __user *user_buf,
327                                           size_t count, loff_t *ppos)
328 {
329         struct iwl_priv *priv = file->private_data;
330
331         if (!priv->wowlan_sram)
332                 return -ENODATA;
333
334         return simple_read_from_buffer(user_buf, count, ppos,
335                                        priv->wowlan_sram,
336                                        priv->ucode_wowlan.data.len);
337 }
338 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
339                                         size_t count, loff_t *ppos)
340 {
341         struct iwl_priv *priv = file->private_data;
342         struct iwl_station_entry *station;
343         int max_sta = hw_params(priv).max_stations;
344         char *buf;
345         int i, j, pos = 0;
346         ssize_t ret;
347         /* Add 30 for initial string */
348         const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
349
350         buf = kmalloc(bufsz, GFP_KERNEL);
351         if (!buf)
352                 return -ENOMEM;
353
354         pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
355                         priv->num_stations);
356
357         for (i = 0; i < max_sta; i++) {
358                 station = &priv->stations[i];
359                 if (!station->used)
360                         continue;
361                 pos += scnprintf(buf + pos, bufsz - pos,
362                                  "station %d - addr: %pM, flags: %#x\n",
363                                  i, station->sta.sta.addr,
364                                  station->sta.station_flags_msk);
365                 pos += scnprintf(buf + pos, bufsz - pos,
366                                 "TID\tseq_num\ttxq_id\tframes\ttfds\t");
367                 pos += scnprintf(buf + pos, bufsz - pos,
368                                 "start_idx\tbitmap\t\t\trate_n_flags\n");
369
370                 for (j = 0; j < MAX_TID_COUNT; j++) {
371                         pos += scnprintf(buf + pos, bufsz - pos,
372                                 "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
373                                 j, station->tid[j].seq_number,
374                                 station->tid[j].agg.txq_id,
375                                 station->tid[j].agg.frame_count,
376                                 station->tid[j].tfds_in_queue,
377                                 station->tid[j].agg.start_idx,
378                                 station->tid[j].agg.bitmap,
379                                 station->tid[j].agg.rate_n_flags);
380
381                         if (station->tid[j].agg.wait_for_ba)
382                                 pos += scnprintf(buf + pos, bufsz - pos,
383                                                  " - waitforba");
384                         pos += scnprintf(buf + pos, bufsz - pos, "\n");
385                 }
386
387                 pos += scnprintf(buf + pos, bufsz - pos, "\n");
388         }
389
390         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
391         kfree(buf);
392         return ret;
393 }
394
395 static ssize_t iwl_dbgfs_nvm_read(struct file *file,
396                                        char __user *user_buf,
397                                        size_t count,
398                                        loff_t *ppos)
399 {
400         ssize_t ret;
401         struct iwl_priv *priv = file->private_data;
402         int pos = 0, ofs = 0, buf_size = 0;
403         const u8 *ptr;
404         char *buf;
405         u16 eeprom_ver;
406         size_t eeprom_len = priv->cfg->base_params->eeprom_size;
407         buf_size = 4 * eeprom_len + 256;
408
409         if (eeprom_len % 16) {
410                 IWL_ERR(priv, "NVM size is not multiple of 16.\n");
411                 return -ENODATA;
412         }
413
414         ptr = priv->eeprom;
415         if (!ptr) {
416                 IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
417                 return -ENOMEM;
418         }
419
420         /* 4 characters for byte 0xYY */
421         buf = kzalloc(buf_size, GFP_KERNEL);
422         if (!buf) {
423                 IWL_ERR(priv, "Can not allocate Buffer\n");
424                 return -ENOMEM;
425         }
426         eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
427         pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
428                         "version: 0x%x\n",
429                         (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
430                          ? "OTP" : "EEPROM", eeprom_ver);
431         for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
432                 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
433                 hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
434                                    buf_size - pos, 0);
435                 pos += strlen(buf + pos);
436                 if (buf_size - pos > 0)
437                         buf[pos++] = '\n';
438         }
439
440         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
441         kfree(buf);
442         return ret;
443 }
444
445 static ssize_t iwl_dbgfs_log_event_read(struct file *file,
446                                          char __user *user_buf,
447                                          size_t count, loff_t *ppos)
448 {
449         struct iwl_priv *priv = file->private_data;
450         char *buf;
451         int pos = 0;
452         ssize_t ret = -ENOMEM;
453
454         ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);
455         if (buf) {
456                 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
457                 kfree(buf);
458         }
459         return ret;
460 }
461
462 static ssize_t iwl_dbgfs_log_event_write(struct file *file,
463                                         const char __user *user_buf,
464                                         size_t count, loff_t *ppos)
465 {
466         struct iwl_priv *priv = file->private_data;
467         u32 event_log_flag;
468         char buf[8];
469         int buf_size;
470
471         memset(buf, 0, sizeof(buf));
472         buf_size = min(count, sizeof(buf) -  1);
473         if (copy_from_user(buf, user_buf, buf_size))
474                 return -EFAULT;
475         if (sscanf(buf, "%d", &event_log_flag) != 1)
476                 return -EFAULT;
477         if (event_log_flag == 1)
478                 iwl_dump_nic_event_log(priv, true, NULL, false);
479
480         return count;
481 }
482
483
484
485 static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
486                                        size_t count, loff_t *ppos)
487 {
488         struct iwl_priv *priv = file->private_data;
489         struct ieee80211_channel *channels = NULL;
490         const struct ieee80211_supported_band *supp_band = NULL;
491         int pos = 0, i, bufsz = PAGE_SIZE;
492         char *buf;
493         ssize_t ret;
494
495         if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
496                 return -EAGAIN;
497
498         buf = kzalloc(bufsz, GFP_KERNEL);
499         if (!buf) {
500                 IWL_ERR(priv, "Can not allocate Buffer\n");
501                 return -ENOMEM;
502         }
503
504         supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
505         if (supp_band) {
506                 channels = supp_band->channels;
507
508                 pos += scnprintf(buf + pos, bufsz - pos,
509                                 "Displaying %d channels in 2.4GHz band 802.11bg):\n",
510                                 supp_band->n_channels);
511
512                 for (i = 0; i < supp_band->n_channels; i++)
513                         pos += scnprintf(buf + pos, bufsz - pos,
514                                         "%d: %ddBm: BSS%s%s, %s.\n",
515                                         channels[i].hw_value,
516                                         channels[i].max_power,
517                                         channels[i].flags & IEEE80211_CHAN_RADAR ?
518                                         " (IEEE 802.11h required)" : "",
519                                         ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
520                                         || (channels[i].flags &
521                                         IEEE80211_CHAN_RADAR)) ? "" :
522                                         ", IBSS",
523                                         channels[i].flags &
524                                         IEEE80211_CHAN_PASSIVE_SCAN ?
525                                         "passive only" : "active/passive");
526         }
527         supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
528         if (supp_band) {
529                 channels = supp_band->channels;
530
531                 pos += scnprintf(buf + pos, bufsz - pos,
532                                 "Displaying %d channels in 5.2GHz band (802.11a)\n",
533                                 supp_band->n_channels);
534
535                 for (i = 0; i < supp_band->n_channels; i++)
536                         pos += scnprintf(buf + pos, bufsz - pos,
537                                         "%d: %ddBm: BSS%s%s, %s.\n",
538                                         channels[i].hw_value,
539                                         channels[i].max_power,
540                                         channels[i].flags & IEEE80211_CHAN_RADAR ?
541                                         " (IEEE 802.11h required)" : "",
542                                         ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
543                                         || (channels[i].flags &
544                                         IEEE80211_CHAN_RADAR)) ? "" :
545                                         ", IBSS",
546                                         channels[i].flags &
547                                         IEEE80211_CHAN_PASSIVE_SCAN ?
548                                         "passive only" : "active/passive");
549         }
550         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
551         kfree(buf);
552         return ret;
553 }
554
555 static ssize_t iwl_dbgfs_status_read(struct file *file,
556                                                 char __user *user_buf,
557                                                 size_t count, loff_t *ppos) {
558
559         struct iwl_priv *priv = file->private_data;
560         char buf[512];
561         int pos = 0;
562         const size_t bufsz = sizeof(buf);
563
564         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
565                 test_bit(STATUS_HCMD_ACTIVE, &priv->status));
566         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
567                 test_bit(STATUS_INT_ENABLED, &priv->status));
568         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
569                 test_bit(STATUS_RF_KILL_HW, &priv->status));
570         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
571                 test_bit(STATUS_CT_KILL, &priv->status));
572         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
573                 test_bit(STATUS_INIT, &priv->status));
574         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
575                 test_bit(STATUS_ALIVE, &priv->status));
576         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
577                 test_bit(STATUS_READY, &priv->status));
578         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
579                 test_bit(STATUS_TEMPERATURE, &priv->status));
580         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
581                 test_bit(STATUS_GEO_CONFIGURED, &priv->status));
582         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
583                 test_bit(STATUS_EXIT_PENDING, &priv->status));
584         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
585                 test_bit(STATUS_STATISTICS, &priv->status));
586         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
587                 test_bit(STATUS_SCANNING, &priv->status));
588         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
589                 test_bit(STATUS_SCAN_ABORTING, &priv->status));
590         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
591                 test_bit(STATUS_SCAN_HW, &priv->status));
592         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
593                 test_bit(STATUS_POWER_PMI, &priv->status));
594         pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
595                 test_bit(STATUS_FW_ERROR, &priv->status));
596         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
597 }
598
599 static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
600                                         char __user *user_buf,
601                                         size_t count, loff_t *ppos) {
602
603         struct iwl_priv *priv = file->private_data;
604         int pos = 0;
605         int cnt = 0;
606         char *buf;
607         int bufsz = 24 * 64; /* 24 items * 64 char per item */
608         ssize_t ret;
609
610         buf = kzalloc(bufsz, GFP_KERNEL);
611         if (!buf) {
612                 IWL_ERR(priv, "Can not allocate Buffer\n");
613                 return -ENOMEM;
614         }
615
616         pos += scnprintf(buf + pos, bufsz - pos,
617                         "Interrupt Statistics Report:\n");
618
619         pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
620                 priv->isr_stats.hw);
621         pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
622                 priv->isr_stats.sw);
623         if (priv->isr_stats.sw || priv->isr_stats.hw) {
624                 pos += scnprintf(buf + pos, bufsz - pos,
625                         "\tLast Restarting Code:  0x%X\n",
626                         priv->isr_stats.err_code);
627         }
628 #ifdef CONFIG_IWLWIFI_DEBUG
629         pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
630                 priv->isr_stats.sch);
631         pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
632                 priv->isr_stats.alive);
633 #endif
634         pos += scnprintf(buf + pos, bufsz - pos,
635                 "HW RF KILL switch toggled:\t %u\n",
636                 priv->isr_stats.rfkill);
637
638         pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
639                 priv->isr_stats.ctkill);
640
641         pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
642                 priv->isr_stats.wakeup);
643
644         pos += scnprintf(buf + pos, bufsz - pos,
645                 "Rx command responses:\t\t %u\n",
646                 priv->isr_stats.rx);
647         for (cnt = 0; cnt < REPLY_MAX; cnt++) {
648                 if (priv->isr_stats.rx_handlers[cnt] > 0)
649                         pos += scnprintf(buf + pos, bufsz - pos,
650                                 "\tRx handler[%36s]:\t\t %u\n",
651                                 get_cmd_string(cnt),
652                                 priv->isr_stats.rx_handlers[cnt]);
653         }
654
655         pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
656                 priv->isr_stats.tx);
657
658         pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
659                 priv->isr_stats.unhandled);
660
661         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
662         kfree(buf);
663         return ret;
664 }
665
666 static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
667                                          const char __user *user_buf,
668                                          size_t count, loff_t *ppos)
669 {
670         struct iwl_priv *priv = file->private_data;
671         char buf[8];
672         int buf_size;
673         u32 reset_flag;
674
675         memset(buf, 0, sizeof(buf));
676         buf_size = min(count, sizeof(buf) -  1);
677         if (copy_from_user(buf, user_buf, buf_size))
678                 return -EFAULT;
679         if (sscanf(buf, "%x", &reset_flag) != 1)
680                 return -EFAULT;
681         if (reset_flag == 0)
682                 iwl_clear_isr_stats(priv);
683
684         return count;
685 }
686
687 static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
688                                        size_t count, loff_t *ppos)
689 {
690         struct iwl_priv *priv = file->private_data;
691         struct iwl_rxon_context *ctx;
692         int pos = 0, i;
693         char buf[256 * NUM_IWL_RXON_CTX];
694         const size_t bufsz = sizeof(buf);
695
696         for_each_context(priv, ctx) {
697                 pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
698                                  ctx->ctxid);
699                 for (i = 0; i < AC_NUM; i++) {
700                         pos += scnprintf(buf + pos, bufsz - pos,
701                                 "\tcw_min\tcw_max\taifsn\ttxop\n");
702                         pos += scnprintf(buf + pos, bufsz - pos,
703                                 "AC[%d]\t%u\t%u\t%u\t%u\n", i,
704                                 ctx->qos_data.def_qos_parm.ac[i].cw_min,
705                                 ctx->qos_data.def_qos_parm.ac[i].cw_max,
706                                 ctx->qos_data.def_qos_parm.ac[i].aifsn,
707                                 ctx->qos_data.def_qos_parm.ac[i].edca_txop);
708                 }
709                 pos += scnprintf(buf + pos, bufsz - pos, "\n");
710         }
711         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
712 }
713
714 static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
715                                 char __user *user_buf,
716                                 size_t count, loff_t *ppos)
717 {
718         struct iwl_priv *priv = file->private_data;
719         struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
720         struct iwl_tt_restriction *restriction;
721         char buf[100];
722         int pos = 0;
723         const size_t bufsz = sizeof(buf);
724
725         pos += scnprintf(buf + pos, bufsz - pos,
726                         "Thermal Throttling Mode: %s\n",
727                         tt->advanced_tt ? "Advance" : "Legacy");
728         pos += scnprintf(buf + pos, bufsz - pos,
729                         "Thermal Throttling State: %d\n",
730                         tt->state);
731         if (tt->advanced_tt) {
732                 restriction = tt->restriction + tt->state;
733                 pos += scnprintf(buf + pos, bufsz - pos,
734                                 "Tx mode: %d\n",
735                                 restriction->tx_stream);
736                 pos += scnprintf(buf + pos, bufsz - pos,
737                                 "Rx mode: %d\n",
738                                 restriction->rx_stream);
739                 pos += scnprintf(buf + pos, bufsz - pos,
740                                 "HT mode: %d\n",
741                                 restriction->is_ht);
742         }
743         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
744 }
745
746 static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
747                                          const char __user *user_buf,
748                                          size_t count, loff_t *ppos)
749 {
750         struct iwl_priv *priv = file->private_data;
751         char buf[8];
752         int buf_size;
753         int ht40;
754
755         memset(buf, 0, sizeof(buf));
756         buf_size = min(count, sizeof(buf) -  1);
757         if (copy_from_user(buf, user_buf, buf_size))
758                 return -EFAULT;
759         if (sscanf(buf, "%d", &ht40) != 1)
760                 return -EFAULT;
761         if (!iwl_is_any_associated(priv))
762                 priv->disable_ht40 = ht40 ? true : false;
763         else {
764                 IWL_ERR(priv, "Sta associated with AP - "
765                         "Change to 40MHz channel support is not allowed\n");
766                 return -EINVAL;
767         }
768
769         return count;
770 }
771
772 static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
773                                          char __user *user_buf,
774                                          size_t count, loff_t *ppos)
775 {
776         struct iwl_priv *priv = file->private_data;
777         char buf[100];
778         int pos = 0;
779         const size_t bufsz = sizeof(buf);
780
781         pos += scnprintf(buf + pos, bufsz - pos,
782                         "11n 40MHz Mode: %s\n",
783                         priv->disable_ht40 ? "Disabled" : "Enabled");
784         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
785 }
786
787 static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
788                                                     const char __user *user_buf,
789                                                     size_t count, loff_t *ppos)
790 {
791         struct iwl_priv *priv = file->private_data;
792         char buf[8];
793         int buf_size;
794         int value;
795
796         memset(buf, 0, sizeof(buf));
797         buf_size = min(count, sizeof(buf) -  1);
798         if (copy_from_user(buf, user_buf, buf_size))
799                 return -EFAULT;
800
801         if (sscanf(buf, "%d", &value) != 1)
802                 return -EINVAL;
803
804         /*
805          * Our users expect 0 to be "CAM", but 0 isn't actually
806          * valid here. However, let's not confuse them and present
807          * IWL_POWER_INDEX_1 as "1", not "0".
808          */
809         if (value == 0)
810                 return -EINVAL;
811         else if (value > 0)
812                 value -= 1;
813
814         if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
815                 return -EINVAL;
816
817         if (!iwl_is_ready_rf(priv))
818                 return -EAGAIN;
819
820         priv->power_data.debug_sleep_level_override = value;
821
822         mutex_lock(&priv->mutex);
823         iwl_power_update_mode(priv, true);
824         mutex_unlock(&priv->mutex);
825
826         return count;
827 }
828
829 static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
830                                                    char __user *user_buf,
831                                                    size_t count, loff_t *ppos)
832 {
833         struct iwl_priv *priv = file->private_data;
834         char buf[10];
835         int pos, value;
836         const size_t bufsz = sizeof(buf);
837
838         /* see the write function */
839         value = priv->power_data.debug_sleep_level_override;
840         if (value >= 0)
841                 value += 1;
842
843         pos = scnprintf(buf, bufsz, "%d\n", value);
844         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
845 }
846
847 static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
848                                                     char __user *user_buf,
849                                                     size_t count, loff_t *ppos)
850 {
851         struct iwl_priv *priv = file->private_data;
852         char buf[200];
853         int pos = 0, i;
854         const size_t bufsz = sizeof(buf);
855         struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
856
857         pos += scnprintf(buf + pos, bufsz - pos,
858                          "flags: %#.2x\n", le16_to_cpu(cmd->flags));
859         pos += scnprintf(buf + pos, bufsz - pos,
860                          "RX/TX timeout: %d/%d usec\n",
861                          le32_to_cpu(cmd->rx_data_timeout),
862                          le32_to_cpu(cmd->tx_data_timeout));
863         for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
864                 pos += scnprintf(buf + pos, bufsz - pos,
865                                  "sleep_interval[%d]: %d\n", i,
866                                  le32_to_cpu(cmd->sleep_interval[i]));
867
868         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
869 }
870
871 DEBUGFS_READ_WRITE_FILE_OPS(sram);
872 DEBUGFS_READ_FILE_OPS(wowlan_sram);
873 DEBUGFS_READ_WRITE_FILE_OPS(log_event);
874 DEBUGFS_READ_FILE_OPS(nvm);
875 DEBUGFS_READ_FILE_OPS(stations);
876 DEBUGFS_READ_FILE_OPS(channels);
877 DEBUGFS_READ_FILE_OPS(status);
878 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
879 DEBUGFS_READ_FILE_OPS(qos);
880 DEBUGFS_READ_FILE_OPS(thermal_throttling);
881 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
882 DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
883 DEBUGFS_READ_FILE_OPS(current_sleep_command);
884
885 static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
886                                          char __user *user_buf,
887                                          size_t count, loff_t *ppos)
888 {
889         struct iwl_priv *priv = file->private_data;
890         int pos = 0, ofs = 0;
891         int cnt = 0, entry;
892         struct iwl_tx_queue *txq;
893         struct iwl_queue *q;
894         struct iwl_rx_queue *rxq = &priv->rxq;
895         char *buf;
896         int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
897                 (priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
898         const u8 *ptr;
899         ssize_t ret;
900
901         if (!priv->txq) {
902                 IWL_ERR(priv, "txq not ready\n");
903                 return -EAGAIN;
904         }
905         buf = kzalloc(bufsz, GFP_KERNEL);
906         if (!buf) {
907                 IWL_ERR(priv, "Can not allocate buffer\n");
908                 return -ENOMEM;
909         }
910         pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
911         for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
912                 txq = &priv->txq[cnt];
913                 q = &txq->q;
914                 pos += scnprintf(buf + pos, bufsz - pos,
915                                 "q[%d]: read_ptr: %u, write_ptr: %u\n",
916                                 cnt, q->read_ptr, q->write_ptr);
917         }
918         if (priv->tx_traffic &&
919                 (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
920                 ptr = priv->tx_traffic;
921                 pos += scnprintf(buf + pos, bufsz - pos,
922                                 "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
923                 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
924                         for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
925                              entry++,  ofs += 16) {
926                                 pos += scnprintf(buf + pos, bufsz - pos,
927                                                 "0x%.4x ", ofs);
928                                 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
929                                                    buf + pos, bufsz - pos, 0);
930                                 pos += strlen(buf + pos);
931                                 if (bufsz - pos > 0)
932                                         buf[pos++] = '\n';
933                         }
934                 }
935         }
936
937         pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
938         pos += scnprintf(buf + pos, bufsz - pos,
939                         "read: %u, write: %u\n",
940                          rxq->read, rxq->write);
941
942         if (priv->rx_traffic &&
943                 (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
944                 ptr = priv->rx_traffic;
945                 pos += scnprintf(buf + pos, bufsz - pos,
946                                 "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
947                 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
948                         for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
949                              entry++,  ofs += 16) {
950                                 pos += scnprintf(buf + pos, bufsz - pos,
951                                                 "0x%.4x ", ofs);
952                                 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
953                                                    buf + pos, bufsz - pos, 0);
954                                 pos += strlen(buf + pos);
955                                 if (bufsz - pos > 0)
956                                         buf[pos++] = '\n';
957                         }
958                 }
959         }
960
961         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
962         kfree(buf);
963         return ret;
964 }
965
966 static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
967                                          const char __user *user_buf,
968                                          size_t count, loff_t *ppos)
969 {
970         struct iwl_priv *priv = file->private_data;
971         char buf[8];
972         int buf_size;
973         int traffic_log;
974
975         memset(buf, 0, sizeof(buf));
976         buf_size = min(count, sizeof(buf) -  1);
977         if (copy_from_user(buf, user_buf, buf_size))
978                 return -EFAULT;
979         if (sscanf(buf, "%d", &traffic_log) != 1)
980                 return -EFAULT;
981         if (traffic_log == 0)
982                 iwl_reset_traffic_log(priv);
983
984         return count;
985 }
986
987 static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
988                                                 char __user *user_buf,
989                                                 size_t count, loff_t *ppos) {
990
991         struct iwl_priv *priv = file->private_data;
992         struct iwl_tx_queue *txq;
993         struct iwl_queue *q;
994         char *buf;
995         int pos = 0;
996         int cnt;
997         int ret;
998         const size_t bufsz = sizeof(char) * 64 *
999                                 priv->cfg->base_params->num_of_queues;
1000
1001         if (!priv->txq) {
1002                 IWL_ERR(priv, "txq not ready\n");
1003                 return -EAGAIN;
1004         }
1005         buf = kzalloc(bufsz, GFP_KERNEL);
1006         if (!buf)
1007                 return -ENOMEM;
1008
1009         for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
1010                 txq = &priv->txq[cnt];
1011                 q = &txq->q;
1012                 pos += scnprintf(buf + pos, bufsz - pos,
1013                                 "hwq %.2d: read=%u write=%u stop=%d"
1014                                 " swq_id=%#.2x (ac %d/hwq %d)\n",
1015                                 cnt, q->read_ptr, q->write_ptr,
1016                                 !!test_bit(cnt, priv->queue_stopped),
1017                                 txq->swq_id, txq->swq_id & 3,
1018                                 (txq->swq_id >> 2) & 0x1f);
1019                 if (cnt >= 4)
1020                         continue;
1021                 /* for the ACs, display the stop count too */
1022                 pos += scnprintf(buf + pos, bufsz - pos,
1023                                 "        stop-count: %d\n",
1024                                 atomic_read(&priv->queue_stop_count[cnt]));
1025         }
1026         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1027         kfree(buf);
1028         return ret;
1029 }
1030
1031 static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
1032                                                 char __user *user_buf,
1033                                                 size_t count, loff_t *ppos) {
1034
1035         struct iwl_priv *priv = file->private_data;
1036         struct iwl_rx_queue *rxq = &priv->rxq;
1037         char buf[256];
1038         int pos = 0;
1039         const size_t bufsz = sizeof(buf);
1040
1041         pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
1042                                                 rxq->read);
1043         pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
1044                                                 rxq->write);
1045         pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
1046                                                 rxq->free_count);
1047         if (rxq->rb_stts) {
1048                 pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
1049                          le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
1050         } else {
1051                 pos += scnprintf(buf + pos, bufsz - pos,
1052                                         "closed_rb_num: Not Allocated\n");
1053         }
1054         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1055 }
1056
1057 static const char *fmt_value = "  %-30s %10u\n";
1058 static const char *fmt_hex   = "  %-30s       0x%02X\n";
1059 static const char *fmt_table = "  %-30s %10u  %10u  %10u  %10u\n";
1060 static const char *fmt_header =
1061         "%-32s    current  cumulative       delta         max\n";
1062
1063 static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
1064 {
1065         int p = 0;
1066         u32 flag;
1067
1068         flag = le32_to_cpu(priv->statistics.flag);
1069
1070         p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
1071         if (flag & UCODE_STATISTICS_CLEAR_MSK)
1072                 p += scnprintf(buf + p, bufsz - p,
1073                 "\tStatistics have been cleared\n");
1074         p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
1075                 (flag & UCODE_STATISTICS_FREQUENCY_MSK)
1076                 ? "2.4 GHz" : "5.2 GHz");
1077         p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
1078                 (flag & UCODE_STATISTICS_NARROW_BAND_MSK)
1079                  ? "enabled" : "disabled");
1080
1081         return p;
1082 }
1083
1084 static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
1085                                         char __user *user_buf,
1086                                         size_t count, loff_t *ppos)
1087 {
1088         struct iwl_priv *priv = file->private_data;
1089         int pos = 0;
1090         char *buf;
1091         int bufsz = sizeof(struct statistics_rx_phy) * 40 +
1092                     sizeof(struct statistics_rx_non_phy) * 40 +
1093                     sizeof(struct statistics_rx_ht_phy) * 40 + 400;
1094         ssize_t ret;
1095         struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
1096         struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
1097         struct statistics_rx_non_phy *general, *accum_general;
1098         struct statistics_rx_non_phy *delta_general, *max_general;
1099         struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
1100
1101         if (!iwl_is_alive(priv))
1102                 return -EAGAIN;
1103
1104         buf = kzalloc(bufsz, GFP_KERNEL);
1105         if (!buf) {
1106                 IWL_ERR(priv, "Can not allocate Buffer\n");
1107                 return -ENOMEM;
1108         }
1109
1110         /*
1111          * the statistic information display here is based on
1112          * the last statistics notification from uCode
1113          * might not reflect the current uCode activity
1114          */
1115         ofdm = &priv->statistics.rx_ofdm;
1116         cck = &priv->statistics.rx_cck;
1117         general = &priv->statistics.rx_non_phy;
1118         ht = &priv->statistics.rx_ofdm_ht;
1119         accum_ofdm = &priv->accum_stats.rx_ofdm;
1120         accum_cck = &priv->accum_stats.rx_cck;
1121         accum_general = &priv->accum_stats.rx_non_phy;
1122         accum_ht = &priv->accum_stats.rx_ofdm_ht;
1123         delta_ofdm = &priv->delta_stats.rx_ofdm;
1124         delta_cck = &priv->delta_stats.rx_cck;
1125         delta_general = &priv->delta_stats.rx_non_phy;
1126         delta_ht = &priv->delta_stats.rx_ofdm_ht;
1127         max_ofdm = &priv->max_delta_stats.rx_ofdm;
1128         max_cck = &priv->max_delta_stats.rx_cck;
1129         max_general = &priv->max_delta_stats.rx_non_phy;
1130         max_ht = &priv->max_delta_stats.rx_ofdm_ht;
1131
1132         pos += iwl_statistics_flag(priv, buf, bufsz);
1133         pos += scnprintf(buf + pos, bufsz - pos,
1134                          fmt_header, "Statistics_Rx - OFDM:");
1135         pos += scnprintf(buf + pos, bufsz - pos,
1136                          fmt_table, "ina_cnt:",
1137                          le32_to_cpu(ofdm->ina_cnt),
1138                          accum_ofdm->ina_cnt,
1139                          delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
1140         pos += scnprintf(buf + pos, bufsz - pos,
1141                          fmt_table, "fina_cnt:",
1142                          le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
1143                          delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
1144         pos += scnprintf(buf + pos, bufsz - pos,
1145                          fmt_table, "plcp_err:",
1146                          le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
1147                          delta_ofdm->plcp_err, max_ofdm->plcp_err);
1148         pos += scnprintf(buf + pos, bufsz - pos,
1149                          fmt_table, "crc32_err:",
1150                          le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
1151                          delta_ofdm->crc32_err, max_ofdm->crc32_err);
1152         pos += scnprintf(buf + pos, bufsz - pos,
1153                          fmt_table, "overrun_err:",
1154                          le32_to_cpu(ofdm->overrun_err),
1155                          accum_ofdm->overrun_err, delta_ofdm->overrun_err,
1156                          max_ofdm->overrun_err);
1157         pos += scnprintf(buf + pos, bufsz - pos,
1158                          fmt_table, "early_overrun_err:",
1159                          le32_to_cpu(ofdm->early_overrun_err),
1160                          accum_ofdm->early_overrun_err,
1161                          delta_ofdm->early_overrun_err,
1162                          max_ofdm->early_overrun_err);
1163         pos += scnprintf(buf + pos, bufsz - pos,
1164                          fmt_table, "crc32_good:",
1165                          le32_to_cpu(ofdm->crc32_good),
1166                          accum_ofdm->crc32_good, delta_ofdm->crc32_good,
1167                          max_ofdm->crc32_good);
1168         pos += scnprintf(buf + pos, bufsz - pos,
1169                          fmt_table, "false_alarm_cnt:",
1170                          le32_to_cpu(ofdm->false_alarm_cnt),
1171                          accum_ofdm->false_alarm_cnt,
1172                          delta_ofdm->false_alarm_cnt,
1173                          max_ofdm->false_alarm_cnt);
1174         pos += scnprintf(buf + pos, bufsz - pos,
1175                          fmt_table, "fina_sync_err_cnt:",
1176                          le32_to_cpu(ofdm->fina_sync_err_cnt),
1177                          accum_ofdm->fina_sync_err_cnt,
1178                          delta_ofdm->fina_sync_err_cnt,
1179                          max_ofdm->fina_sync_err_cnt);
1180         pos += scnprintf(buf + pos, bufsz - pos,
1181                          fmt_table, "sfd_timeout:",
1182                          le32_to_cpu(ofdm->sfd_timeout),
1183                          accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,
1184                          max_ofdm->sfd_timeout);
1185         pos += scnprintf(buf + pos, bufsz - pos,
1186                          fmt_table, "fina_timeout:",
1187                          le32_to_cpu(ofdm->fina_timeout),
1188                          accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,
1189                          max_ofdm->fina_timeout);
1190         pos += scnprintf(buf + pos, bufsz - pos,
1191                          fmt_table, "unresponded_rts:",
1192                          le32_to_cpu(ofdm->unresponded_rts),
1193                          accum_ofdm->unresponded_rts,
1194                          delta_ofdm->unresponded_rts,
1195                          max_ofdm->unresponded_rts);
1196         pos += scnprintf(buf + pos, bufsz - pos,
1197                          fmt_table, "rxe_frame_lmt_ovrun:",
1198                          le32_to_cpu(ofdm->rxe_frame_limit_overrun),
1199                          accum_ofdm->rxe_frame_limit_overrun,
1200                          delta_ofdm->rxe_frame_limit_overrun,
1201                          max_ofdm->rxe_frame_limit_overrun);
1202         pos += scnprintf(buf + pos, bufsz - pos,
1203                          fmt_table, "sent_ack_cnt:",
1204                          le32_to_cpu(ofdm->sent_ack_cnt),
1205                          accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,
1206                          max_ofdm->sent_ack_cnt);
1207         pos += scnprintf(buf + pos, bufsz - pos,
1208                          fmt_table, "sent_cts_cnt:",
1209                          le32_to_cpu(ofdm->sent_cts_cnt),
1210                          accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,
1211                          max_ofdm->sent_cts_cnt);
1212         pos += scnprintf(buf + pos, bufsz - pos,
1213                          fmt_table, "sent_ba_rsp_cnt:",
1214                          le32_to_cpu(ofdm->sent_ba_rsp_cnt),
1215                          accum_ofdm->sent_ba_rsp_cnt,
1216                          delta_ofdm->sent_ba_rsp_cnt,
1217                          max_ofdm->sent_ba_rsp_cnt);
1218         pos += scnprintf(buf + pos, bufsz - pos,
1219                          fmt_table, "dsp_self_kill:",
1220                          le32_to_cpu(ofdm->dsp_self_kill),
1221                          accum_ofdm->dsp_self_kill,
1222                          delta_ofdm->dsp_self_kill,
1223                          max_ofdm->dsp_self_kill);
1224         pos += scnprintf(buf + pos, bufsz - pos,
1225                          fmt_table, "mh_format_err:",
1226                          le32_to_cpu(ofdm->mh_format_err),
1227                          accum_ofdm->mh_format_err,
1228                          delta_ofdm->mh_format_err,
1229                          max_ofdm->mh_format_err);
1230         pos += scnprintf(buf + pos, bufsz - pos,
1231                          fmt_table, "re_acq_main_rssi_sum:",
1232                          le32_to_cpu(ofdm->re_acq_main_rssi_sum),
1233                          accum_ofdm->re_acq_main_rssi_sum,
1234                          delta_ofdm->re_acq_main_rssi_sum,
1235                          max_ofdm->re_acq_main_rssi_sum);
1236
1237         pos += scnprintf(buf + pos, bufsz - pos,
1238                          fmt_header, "Statistics_Rx - CCK:");
1239         pos += scnprintf(buf + pos, bufsz - pos,
1240                          fmt_table, "ina_cnt:",
1241                          le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
1242                          delta_cck->ina_cnt, max_cck->ina_cnt);
1243         pos += scnprintf(buf + pos, bufsz - pos,
1244                          fmt_table, "fina_cnt:",
1245                          le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
1246                          delta_cck->fina_cnt, max_cck->fina_cnt);
1247         pos += scnprintf(buf + pos, bufsz - pos,
1248                          fmt_table, "plcp_err:",
1249                          le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
1250                          delta_cck->plcp_err, max_cck->plcp_err);
1251         pos += scnprintf(buf + pos, bufsz - pos,
1252                          fmt_table, "crc32_err:",
1253                          le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
1254                          delta_cck->crc32_err, max_cck->crc32_err);
1255         pos += scnprintf(buf + pos, bufsz - pos,
1256                          fmt_table, "overrun_err:",
1257                          le32_to_cpu(cck->overrun_err),
1258                          accum_cck->overrun_err, delta_cck->overrun_err,
1259                          max_cck->overrun_err);
1260         pos += scnprintf(buf + pos, bufsz - pos,
1261                          fmt_table, "early_overrun_err:",
1262                          le32_to_cpu(cck->early_overrun_err),
1263                          accum_cck->early_overrun_err,
1264                          delta_cck->early_overrun_err,
1265                          max_cck->early_overrun_err);
1266         pos += scnprintf(buf + pos, bufsz - pos,
1267                          fmt_table, "crc32_good:",
1268                          le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
1269                          delta_cck->crc32_good, max_cck->crc32_good);
1270         pos += scnprintf(buf + pos, bufsz - pos,
1271                          fmt_table, "false_alarm_cnt:",
1272                          le32_to_cpu(cck->false_alarm_cnt),
1273                          accum_cck->false_alarm_cnt,
1274                          delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
1275         pos += scnprintf(buf + pos, bufsz - pos,
1276                          fmt_table, "fina_sync_err_cnt:",
1277                          le32_to_cpu(cck->fina_sync_err_cnt),
1278                          accum_cck->fina_sync_err_cnt,
1279                          delta_cck->fina_sync_err_cnt,
1280                          max_cck->fina_sync_err_cnt);
1281         pos += scnprintf(buf + pos, bufsz - pos,
1282                          fmt_table, "sfd_timeout:",
1283                          le32_to_cpu(cck->sfd_timeout),
1284                          accum_cck->sfd_timeout, delta_cck->sfd_timeout,
1285                          max_cck->sfd_timeout);
1286         pos += scnprintf(buf + pos, bufsz - pos,
1287                          fmt_table, "fina_timeout:",
1288                          le32_to_cpu(cck->fina_timeout),
1289                          accum_cck->fina_timeout, delta_cck->fina_timeout,
1290                          max_cck->fina_timeout);
1291         pos += scnprintf(buf + pos, bufsz - pos,
1292                          fmt_table, "unresponded_rts:",
1293                          le32_to_cpu(cck->unresponded_rts),
1294                          accum_cck->unresponded_rts, delta_cck->unresponded_rts,
1295                          max_cck->unresponded_rts);
1296         pos += scnprintf(buf + pos, bufsz - pos,
1297                          fmt_table, "rxe_frame_lmt_ovrun:",
1298                          le32_to_cpu(cck->rxe_frame_limit_overrun),
1299                          accum_cck->rxe_frame_limit_overrun,
1300                          delta_cck->rxe_frame_limit_overrun,
1301                          max_cck->rxe_frame_limit_overrun);
1302         pos += scnprintf(buf + pos, bufsz - pos,
1303                          fmt_table, "sent_ack_cnt:",
1304                          le32_to_cpu(cck->sent_ack_cnt),
1305                          accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,
1306                          max_cck->sent_ack_cnt);
1307         pos += scnprintf(buf + pos, bufsz - pos,
1308                          fmt_table, "sent_cts_cnt:",
1309                          le32_to_cpu(cck->sent_cts_cnt),
1310                          accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,
1311                          max_cck->sent_cts_cnt);
1312         pos += scnprintf(buf + pos, bufsz - pos,
1313                          fmt_table, "sent_ba_rsp_cnt:",
1314                          le32_to_cpu(cck->sent_ba_rsp_cnt),
1315                          accum_cck->sent_ba_rsp_cnt,
1316                          delta_cck->sent_ba_rsp_cnt,
1317                          max_cck->sent_ba_rsp_cnt);
1318         pos += scnprintf(buf + pos, bufsz - pos,
1319                          fmt_table, "dsp_self_kill:",
1320                          le32_to_cpu(cck->dsp_self_kill),
1321                          accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,
1322                          max_cck->dsp_self_kill);
1323         pos += scnprintf(buf + pos, bufsz - pos,
1324                          fmt_table, "mh_format_err:",
1325                          le32_to_cpu(cck->mh_format_err),
1326                          accum_cck->mh_format_err, delta_cck->mh_format_err,
1327                          max_cck->mh_format_err);
1328         pos += scnprintf(buf + pos, bufsz - pos,
1329                          fmt_table, "re_acq_main_rssi_sum:",
1330                          le32_to_cpu(cck->re_acq_main_rssi_sum),
1331                          accum_cck->re_acq_main_rssi_sum,
1332                          delta_cck->re_acq_main_rssi_sum,
1333                          max_cck->re_acq_main_rssi_sum);
1334
1335         pos += scnprintf(buf + pos, bufsz - pos,
1336                          fmt_header, "Statistics_Rx - GENERAL:");
1337         pos += scnprintf(buf + pos, bufsz - pos,
1338                          fmt_table, "bogus_cts:",
1339                          le32_to_cpu(general->bogus_cts),
1340                          accum_general->bogus_cts, delta_general->bogus_cts,
1341                          max_general->bogus_cts);
1342         pos += scnprintf(buf + pos, bufsz - pos,
1343                          fmt_table, "bogus_ack:",
1344                          le32_to_cpu(general->bogus_ack),
1345                          accum_general->bogus_ack, delta_general->bogus_ack,
1346                          max_general->bogus_ack);
1347         pos += scnprintf(buf + pos, bufsz - pos,
1348                          fmt_table, "non_bssid_frames:",
1349                          le32_to_cpu(general->non_bssid_frames),
1350                          accum_general->non_bssid_frames,
1351                          delta_general->non_bssid_frames,
1352                          max_general->non_bssid_frames);
1353         pos += scnprintf(buf + pos, bufsz - pos,
1354                          fmt_table, "filtered_frames:",
1355                          le32_to_cpu(general->filtered_frames),
1356                          accum_general->filtered_frames,
1357                          delta_general->filtered_frames,
1358                          max_general->filtered_frames);
1359         pos += scnprintf(buf + pos, bufsz - pos,
1360                          fmt_table, "non_channel_beacons:",
1361                          le32_to_cpu(general->non_channel_beacons),
1362                          accum_general->non_channel_beacons,
1363                          delta_general->non_channel_beacons,
1364                          max_general->non_channel_beacons);
1365         pos += scnprintf(buf + pos, bufsz - pos,
1366                          fmt_table, "channel_beacons:",
1367                          le32_to_cpu(general->channel_beacons),
1368                          accum_general->channel_beacons,
1369                          delta_general->channel_beacons,
1370                          max_general->channel_beacons);
1371         pos += scnprintf(buf + pos, bufsz - pos,
1372                          fmt_table, "num_missed_bcon:",
1373                          le32_to_cpu(general->num_missed_bcon),
1374                          accum_general->num_missed_bcon,
1375                          delta_general->num_missed_bcon,
1376                          max_general->num_missed_bcon);
1377         pos += scnprintf(buf + pos, bufsz - pos,
1378                          fmt_table, "adc_rx_saturation_time:",
1379                          le32_to_cpu(general->adc_rx_saturation_time),
1380                          accum_general->adc_rx_saturation_time,
1381                          delta_general->adc_rx_saturation_time,
1382                          max_general->adc_rx_saturation_time);
1383         pos += scnprintf(buf + pos, bufsz - pos,
1384                          fmt_table, "ina_detect_search_tm:",
1385                          le32_to_cpu(general->ina_detection_search_time),
1386                          accum_general->ina_detection_search_time,
1387                          delta_general->ina_detection_search_time,
1388                          max_general->ina_detection_search_time);
1389         pos += scnprintf(buf + pos, bufsz - pos,
1390                          fmt_table, "beacon_silence_rssi_a:",
1391                          le32_to_cpu(general->beacon_silence_rssi_a),
1392                          accum_general->beacon_silence_rssi_a,
1393                          delta_general->beacon_silence_rssi_a,
1394                          max_general->beacon_silence_rssi_a);
1395         pos += scnprintf(buf + pos, bufsz - pos,
1396                          fmt_table, "beacon_silence_rssi_b:",
1397                          le32_to_cpu(general->beacon_silence_rssi_b),
1398                          accum_general->beacon_silence_rssi_b,
1399                          delta_general->beacon_silence_rssi_b,
1400                          max_general->beacon_silence_rssi_b);
1401         pos += scnprintf(buf + pos, bufsz - pos,
1402                          fmt_table, "beacon_silence_rssi_c:",
1403                          le32_to_cpu(general->beacon_silence_rssi_c),
1404                          accum_general->beacon_silence_rssi_c,
1405                          delta_general->beacon_silence_rssi_c,
1406                          max_general->beacon_silence_rssi_c);
1407         pos += scnprintf(buf + pos, bufsz - pos,
1408                          fmt_table, "interference_data_flag:",
1409                          le32_to_cpu(general->interference_data_flag),
1410                          accum_general->interference_data_flag,
1411                          delta_general->interference_data_flag,
1412                          max_general->interference_data_flag);
1413         pos += scnprintf(buf + pos, bufsz - pos,
1414                          fmt_table, "channel_load:",
1415                          le32_to_cpu(general->channel_load),
1416                          accum_general->channel_load,
1417                          delta_general->channel_load,
1418                          max_general->channel_load);
1419         pos += scnprintf(buf + pos, bufsz - pos,
1420                          fmt_table, "dsp_false_alarms:",
1421                          le32_to_cpu(general->dsp_false_alarms),
1422                          accum_general->dsp_false_alarms,
1423                          delta_general->dsp_false_alarms,
1424                          max_general->dsp_false_alarms);
1425         pos += scnprintf(buf + pos, bufsz - pos,
1426                          fmt_table, "beacon_rssi_a:",
1427                          le32_to_cpu(general->beacon_rssi_a),
1428                          accum_general->beacon_rssi_a,
1429                          delta_general->beacon_rssi_a,
1430                          max_general->beacon_rssi_a);
1431         pos += scnprintf(buf + pos, bufsz - pos,
1432                          fmt_table, "beacon_rssi_b:",
1433                          le32_to_cpu(general->beacon_rssi_b),
1434                          accum_general->beacon_rssi_b,
1435                          delta_general->beacon_rssi_b,
1436                          max_general->beacon_rssi_b);
1437         pos += scnprintf(buf + pos, bufsz - pos,
1438                          fmt_table, "beacon_rssi_c:",
1439                          le32_to_cpu(general->beacon_rssi_c),
1440                          accum_general->beacon_rssi_c,
1441                          delta_general->beacon_rssi_c,
1442                          max_general->beacon_rssi_c);
1443         pos += scnprintf(buf + pos, bufsz - pos,
1444                          fmt_table, "beacon_energy_a:",
1445                          le32_to_cpu(general->beacon_energy_a),
1446                          accum_general->beacon_energy_a,
1447                          delta_general->beacon_energy_a,
1448                          max_general->beacon_energy_a);
1449         pos += scnprintf(buf + pos, bufsz - pos,
1450                          fmt_table, "beacon_energy_b:",
1451                          le32_to_cpu(general->beacon_energy_b),
1452                          accum_general->beacon_energy_b,
1453                          delta_general->beacon_energy_b,
1454                          max_general->beacon_energy_b);
1455         pos += scnprintf(buf + pos, bufsz - pos,
1456                          fmt_table, "beacon_energy_c:",
1457                          le32_to_cpu(general->beacon_energy_c),
1458                          accum_general->beacon_energy_c,
1459                          delta_general->beacon_energy_c,
1460                          max_general->beacon_energy_c);
1461
1462         pos += scnprintf(buf + pos, bufsz - pos,
1463                          fmt_header, "Statistics_Rx - OFDM_HT:");
1464         pos += scnprintf(buf + pos, bufsz - pos,
1465                          fmt_table, "plcp_err:",
1466                          le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
1467                          delta_ht->plcp_err, max_ht->plcp_err);
1468         pos += scnprintf(buf + pos, bufsz - pos,
1469                          fmt_table, "overrun_err:",
1470                          le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
1471                          delta_ht->overrun_err, max_ht->overrun_err);
1472         pos += scnprintf(buf + pos, bufsz - pos,
1473                          fmt_table, "early_overrun_err:",
1474                          le32_to_cpu(ht->early_overrun_err),
1475                          accum_ht->early_overrun_err,
1476                          delta_ht->early_overrun_err,
1477                          max_ht->early_overrun_err);
1478         pos += scnprintf(buf + pos, bufsz - pos,
1479                          fmt_table, "crc32_good:",
1480                          le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
1481                          delta_ht->crc32_good, max_ht->crc32_good);
1482         pos += scnprintf(buf + pos, bufsz - pos,
1483                          fmt_table, "crc32_err:",
1484                          le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
1485                          delta_ht->crc32_err, max_ht->crc32_err);
1486         pos += scnprintf(buf + pos, bufsz - pos,
1487                          fmt_table, "mh_format_err:",
1488                          le32_to_cpu(ht->mh_format_err),
1489                          accum_ht->mh_format_err,
1490                          delta_ht->mh_format_err, max_ht->mh_format_err);
1491         pos += scnprintf(buf + pos, bufsz - pos,
1492                          fmt_table, "agg_crc32_good:",
1493                          le32_to_cpu(ht->agg_crc32_good),
1494                          accum_ht->agg_crc32_good,
1495                          delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
1496         pos += scnprintf(buf + pos, bufsz - pos,
1497                          fmt_table, "agg_mpdu_cnt:",
1498                          le32_to_cpu(ht->agg_mpdu_cnt),
1499                          accum_ht->agg_mpdu_cnt,
1500                          delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
1501         pos += scnprintf(buf + pos, bufsz - pos,
1502                          fmt_table, "agg_cnt:",
1503                          le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
1504                          delta_ht->agg_cnt, max_ht->agg_cnt);
1505         pos += scnprintf(buf + pos, bufsz - pos,
1506                          fmt_table, "unsupport_mcs:",
1507                          le32_to_cpu(ht->unsupport_mcs),
1508                          accum_ht->unsupport_mcs,
1509                          delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
1510
1511         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1512         kfree(buf);
1513         return ret;
1514 }
1515
1516 static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1517                                         char __user *user_buf,
1518                                         size_t count, loff_t *ppos)
1519 {
1520         struct iwl_priv *priv = file->private_data;
1521         int pos = 0;
1522         char *buf;
1523         int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
1524         ssize_t ret;
1525         struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
1526
1527         if (!iwl_is_alive(priv))
1528                 return -EAGAIN;
1529
1530         buf = kzalloc(bufsz, GFP_KERNEL);
1531         if (!buf) {
1532                 IWL_ERR(priv, "Can not allocate Buffer\n");
1533                 return -ENOMEM;
1534         }
1535
1536         /* the statistic information display here is based on
1537          * the last statistics notification from uCode
1538          * might not reflect the current uCode activity
1539          */
1540         tx = &priv->statistics.tx;
1541         accum_tx = &priv->accum_stats.tx;
1542         delta_tx = &priv->delta_stats.tx;
1543         max_tx = &priv->max_delta_stats.tx;
1544
1545         pos += iwl_statistics_flag(priv, buf, bufsz);
1546         pos += scnprintf(buf + pos, bufsz - pos,
1547                          fmt_header, "Statistics_Tx:");
1548         pos += scnprintf(buf + pos, bufsz - pos,
1549                          fmt_table, "preamble:",
1550                          le32_to_cpu(tx->preamble_cnt),
1551                          accum_tx->preamble_cnt,
1552                          delta_tx->preamble_cnt, max_tx->preamble_cnt);
1553         pos += scnprintf(buf + pos, bufsz - pos,
1554                          fmt_table, "rx_detected_cnt:",
1555                          le32_to_cpu(tx->rx_detected_cnt),
1556                          accum_tx->rx_detected_cnt,
1557                          delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
1558         pos += scnprintf(buf + pos, bufsz - pos,
1559                          fmt_table, "bt_prio_defer_cnt:",
1560                          le32_to_cpu(tx->bt_prio_defer_cnt),
1561                          accum_tx->bt_prio_defer_cnt,
1562                          delta_tx->bt_prio_defer_cnt,
1563                          max_tx->bt_prio_defer_cnt);
1564         pos += scnprintf(buf + pos, bufsz - pos,
1565                          fmt_table, "bt_prio_kill_cnt:",
1566                          le32_to_cpu(tx->bt_prio_kill_cnt),
1567                          accum_tx->bt_prio_kill_cnt,
1568                          delta_tx->bt_prio_kill_cnt,
1569                          max_tx->bt_prio_kill_cnt);
1570         pos += scnprintf(buf + pos, bufsz - pos,
1571                          fmt_table, "few_bytes_cnt:",
1572                          le32_to_cpu(tx->few_bytes_cnt),
1573                          accum_tx->few_bytes_cnt,
1574                          delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
1575         pos += scnprintf(buf + pos, bufsz - pos,
1576                          fmt_table, "cts_timeout:",
1577                          le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
1578                          delta_tx->cts_timeout, max_tx->cts_timeout);
1579         pos += scnprintf(buf + pos, bufsz - pos,
1580                          fmt_table, "ack_timeout:",
1581                          le32_to_cpu(tx->ack_timeout),
1582                          accum_tx->ack_timeout,
1583                          delta_tx->ack_timeout, max_tx->ack_timeout);
1584         pos += scnprintf(buf + pos, bufsz - pos,
1585                          fmt_table, "expected_ack_cnt:",
1586                          le32_to_cpu(tx->expected_ack_cnt),
1587                          accum_tx->expected_ack_cnt,
1588                          delta_tx->expected_ack_cnt,
1589                          max_tx->expected_ack_cnt);
1590         pos += scnprintf(buf + pos, bufsz - pos,
1591                          fmt_table, "actual_ack_cnt:",
1592                          le32_to_cpu(tx->actual_ack_cnt),
1593                          accum_tx->actual_ack_cnt,
1594                          delta_tx->actual_ack_cnt,
1595                          max_tx->actual_ack_cnt);
1596         pos += scnprintf(buf + pos, bufsz - pos,
1597                          fmt_table, "dump_msdu_cnt:",
1598                          le32_to_cpu(tx->dump_msdu_cnt),
1599                          accum_tx->dump_msdu_cnt,
1600                          delta_tx->dump_msdu_cnt,
1601                          max_tx->dump_msdu_cnt);
1602         pos += scnprintf(buf + pos, bufsz - pos,
1603                          fmt_table, "abort_nxt_frame_mismatch:",
1604                          le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
1605                          accum_tx->burst_abort_next_frame_mismatch_cnt,
1606                          delta_tx->burst_abort_next_frame_mismatch_cnt,
1607                          max_tx->burst_abort_next_frame_mismatch_cnt);
1608         pos += scnprintf(buf + pos, bufsz - pos,
1609                          fmt_table, "abort_missing_nxt_frame:",
1610                          le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
1611                          accum_tx->burst_abort_missing_next_frame_cnt,
1612                          delta_tx->burst_abort_missing_next_frame_cnt,
1613                          max_tx->burst_abort_missing_next_frame_cnt);
1614         pos += scnprintf(buf + pos, bufsz - pos,
1615                          fmt_table, "cts_timeout_collision:",
1616                          le32_to_cpu(tx->cts_timeout_collision),
1617                          accum_tx->cts_timeout_collision,
1618                          delta_tx->cts_timeout_collision,
1619                          max_tx->cts_timeout_collision);
1620         pos += scnprintf(buf + pos, bufsz - pos,
1621                          fmt_table, "ack_ba_timeout_collision:",
1622                          le32_to_cpu(tx->ack_or_ba_timeout_collision),
1623                          accum_tx->ack_or_ba_timeout_collision,
1624                          delta_tx->ack_or_ba_timeout_collision,
1625                          max_tx->ack_or_ba_timeout_collision);
1626         pos += scnprintf(buf + pos, bufsz - pos,
1627                          fmt_table, "agg ba_timeout:",
1628                          le32_to_cpu(tx->agg.ba_timeout),
1629                          accum_tx->agg.ba_timeout,
1630                          delta_tx->agg.ba_timeout,
1631                          max_tx->agg.ba_timeout);
1632         pos += scnprintf(buf + pos, bufsz - pos,
1633                          fmt_table, "agg ba_resched_frames:",
1634                          le32_to_cpu(tx->agg.ba_reschedule_frames),
1635                          accum_tx->agg.ba_reschedule_frames,
1636                          delta_tx->agg.ba_reschedule_frames,
1637                          max_tx->agg.ba_reschedule_frames);
1638         pos += scnprintf(buf + pos, bufsz - pos,
1639                          fmt_table, "agg scd_query_agg_frame:",
1640                          le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
1641                          accum_tx->agg.scd_query_agg_frame_cnt,
1642                          delta_tx->agg.scd_query_agg_frame_cnt,
1643                          max_tx->agg.scd_query_agg_frame_cnt);
1644         pos += scnprintf(buf + pos, bufsz - pos,
1645                          fmt_table, "agg scd_query_no_agg:",
1646                          le32_to_cpu(tx->agg.scd_query_no_agg),
1647                          accum_tx->agg.scd_query_no_agg,
1648                          delta_tx->agg.scd_query_no_agg,
1649                          max_tx->agg.scd_query_no_agg);
1650         pos += scnprintf(buf + pos, bufsz - pos,
1651                          fmt_table, "agg scd_query_agg:",
1652                          le32_to_cpu(tx->agg.scd_query_agg),
1653                          accum_tx->agg.scd_query_agg,
1654                          delta_tx->agg.scd_query_agg,
1655                          max_tx->agg.scd_query_agg);
1656         pos += scnprintf(buf + pos, bufsz - pos,
1657                          fmt_table, "agg scd_query_mismatch:",
1658                          le32_to_cpu(tx->agg.scd_query_mismatch),
1659                          accum_tx->agg.scd_query_mismatch,
1660                          delta_tx->agg.scd_query_mismatch,
1661                          max_tx->agg.scd_query_mismatch);
1662         pos += scnprintf(buf + pos, bufsz - pos,
1663                          fmt_table, "agg frame_not_ready:",
1664                          le32_to_cpu(tx->agg.frame_not_ready),
1665                          accum_tx->agg.frame_not_ready,
1666                          delta_tx->agg.frame_not_ready,
1667                          max_tx->agg.frame_not_ready);
1668         pos += scnprintf(buf + pos, bufsz - pos,
1669                          fmt_table, "agg underrun:",
1670                          le32_to_cpu(tx->agg.underrun),
1671                          accum_tx->agg.underrun,
1672                          delta_tx->agg.underrun, max_tx->agg.underrun);
1673         pos += scnprintf(buf + pos, bufsz - pos,
1674                          fmt_table, "agg bt_prio_kill:",
1675                          le32_to_cpu(tx->agg.bt_prio_kill),
1676                          accum_tx->agg.bt_prio_kill,
1677                          delta_tx->agg.bt_prio_kill,
1678                          max_tx->agg.bt_prio_kill);
1679         pos += scnprintf(buf + pos, bufsz - pos,
1680                          fmt_table, "agg rx_ba_rsp_cnt:",
1681                          le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
1682                          accum_tx->agg.rx_ba_rsp_cnt,
1683                          delta_tx->agg.rx_ba_rsp_cnt,
1684                          max_tx->agg.rx_ba_rsp_cnt);
1685
1686         if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
1687                 pos += scnprintf(buf + pos, bufsz - pos,
1688                         "tx power: (1/2 dB step)\n");
1689                 if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
1690                         pos += scnprintf(buf + pos, bufsz - pos,
1691                                         fmt_hex, "antenna A:",
1692                                         tx->tx_power.ant_a);
1693                 if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
1694                         pos += scnprintf(buf + pos, bufsz - pos,
1695                                         fmt_hex, "antenna B:",
1696                                         tx->tx_power.ant_b);
1697                 if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
1698                         pos += scnprintf(buf + pos, bufsz - pos,
1699                                         fmt_hex, "antenna C:",
1700                                         tx->tx_power.ant_c);
1701         }
1702         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1703         kfree(buf);
1704         return ret;
1705 }
1706
1707 static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1708                                         char __user *user_buf,
1709                                         size_t count, loff_t *ppos)
1710 {
1711         struct iwl_priv *priv = file->private_data;
1712         int pos = 0;
1713         char *buf;
1714         int bufsz = sizeof(struct statistics_general) * 10 + 300;
1715         ssize_t ret;
1716         struct statistics_general_common *general, *accum_general;
1717         struct statistics_general_common *delta_general, *max_general;
1718         struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
1719         struct statistics_div *div, *accum_div, *delta_div, *max_div;
1720
1721         if (!iwl_is_alive(priv))
1722                 return -EAGAIN;
1723
1724         buf = kzalloc(bufsz, GFP_KERNEL);
1725         if (!buf) {
1726                 IWL_ERR(priv, "Can not allocate Buffer\n");
1727                 return -ENOMEM;
1728         }
1729
1730         /* the statistic information display here is based on
1731          * the last statistics notification from uCode
1732          * might not reflect the current uCode activity
1733          */
1734         general = &priv->statistics.common;
1735         dbg = &priv->statistics.common.dbg;
1736         div = &priv->statistics.common.div;
1737         accum_general = &priv->accum_stats.common;
1738         accum_dbg = &priv->accum_stats.common.dbg;
1739         accum_div = &priv->accum_stats.common.div;
1740         delta_general = &priv->delta_stats.common;
1741         max_general = &priv->max_delta_stats.common;
1742         delta_dbg = &priv->delta_stats.common.dbg;
1743         max_dbg = &priv->max_delta_stats.common.dbg;
1744         delta_div = &priv->delta_stats.common.div;
1745         max_div = &priv->max_delta_stats.common.div;
1746
1747         pos += iwl_statistics_flag(priv, buf, bufsz);
1748         pos += scnprintf(buf + pos, bufsz - pos,
1749                          fmt_header, "Statistics_General:");
1750         pos += scnprintf(buf + pos, bufsz - pos,
1751                          fmt_value, "temperature:",
1752                          le32_to_cpu(general->temperature));
1753         pos += scnprintf(buf + pos, bufsz - pos,
1754                          fmt_value, "temperature_m:",
1755                          le32_to_cpu(general->temperature_m));
1756         pos += scnprintf(buf + pos, bufsz - pos,
1757                          fmt_value, "ttl_timestamp:",
1758                          le32_to_cpu(general->ttl_timestamp));
1759         pos += scnprintf(buf + pos, bufsz - pos,
1760                          fmt_table, "burst_check:",
1761                          le32_to_cpu(dbg->burst_check),
1762                          accum_dbg->burst_check,
1763                          delta_dbg->burst_check, max_dbg->burst_check);
1764         pos += scnprintf(buf + pos, bufsz - pos,
1765                          fmt_table, "burst_count:",
1766                          le32_to_cpu(dbg->burst_count),
1767                          accum_dbg->burst_count,
1768                          delta_dbg->burst_count, max_dbg->burst_count);
1769         pos += scnprintf(buf + pos, bufsz - pos,
1770                          fmt_table, "wait_for_silence_timeout_count:",
1771                          le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
1772                          accum_dbg->wait_for_silence_timeout_cnt,
1773                          delta_dbg->wait_for_silence_timeout_cnt,
1774                          max_dbg->wait_for_silence_timeout_cnt);
1775         pos += scnprintf(buf + pos, bufsz - pos,
1776                          fmt_table, "sleep_time:",
1777                          le32_to_cpu(general->sleep_time),
1778                          accum_general->sleep_time,
1779                          delta_general->sleep_time, max_general->sleep_time);
1780         pos += scnprintf(buf + pos, bufsz - pos,
1781                          fmt_table, "slots_out:",
1782                          le32_to_cpu(general->slots_out),
1783                          accum_general->slots_out,
1784                          delta_general->slots_out, max_general->slots_out);
1785         pos += scnprintf(buf + pos, bufsz - pos,
1786                          fmt_table, "slots_idle:",
1787                          le32_to_cpu(general->slots_idle),
1788                          accum_general->slots_idle,
1789                          delta_general->slots_idle, max_general->slots_idle);
1790         pos += scnprintf(buf + pos, bufsz - pos,
1791                          fmt_table, "tx_on_a:",
1792                          le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
1793                          delta_div->tx_on_a, max_div->tx_on_a);
1794         pos += scnprintf(buf + pos, bufsz - pos,
1795                          fmt_table, "tx_on_b:",
1796                          le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
1797                          delta_div->tx_on_b, max_div->tx_on_b);
1798         pos += scnprintf(buf + pos, bufsz - pos,
1799                          fmt_table, "exec_time:",
1800                          le32_to_cpu(div->exec_time), accum_div->exec_time,
1801                          delta_div->exec_time, max_div->exec_time);
1802         pos += scnprintf(buf + pos, bufsz - pos,
1803                          fmt_table, "probe_time:",
1804                          le32_to_cpu(div->probe_time), accum_div->probe_time,
1805                          delta_div->probe_time, max_div->probe_time);
1806         pos += scnprintf(buf + pos, bufsz - pos,
1807                          fmt_table, "rx_enable_counter:",
1808                          le32_to_cpu(general->rx_enable_counter),
1809                          accum_general->rx_enable_counter,
1810                          delta_general->rx_enable_counter,
1811                          max_general->rx_enable_counter);
1812         pos += scnprintf(buf + pos, bufsz - pos,
1813                          fmt_table, "num_of_sos_states:",
1814                          le32_to_cpu(general->num_of_sos_states),
1815                          accum_general->num_of_sos_states,
1816                          delta_general->num_of_sos_states,
1817                          max_general->num_of_sos_states);
1818         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1819         kfree(buf);
1820         return ret;
1821 }
1822
1823 static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
1824                                         char __user *user_buf,
1825                                         size_t count, loff_t *ppos)
1826 {
1827         struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1828         int pos = 0;
1829         char *buf;
1830         int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200;
1831         ssize_t ret;
1832         struct statistics_bt_activity *bt, *accum_bt;
1833
1834         if (!iwl_is_alive(priv))
1835                 return -EAGAIN;
1836
1837         if (!priv->bt_enable_flag)
1838                 return -EINVAL;
1839
1840         /* make request to uCode to retrieve statistics information */
1841         mutex_lock(&priv->mutex);
1842         ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
1843         mutex_unlock(&priv->mutex);
1844
1845         if (ret) {
1846                 IWL_ERR(priv,
1847                         "Error sending statistics request: %zd\n", ret);
1848                 return -EAGAIN;
1849         }
1850         buf = kzalloc(bufsz, GFP_KERNEL);
1851         if (!buf) {
1852                 IWL_ERR(priv, "Can not allocate Buffer\n");
1853                 return -ENOMEM;
1854         }
1855
1856         /*
1857          * the statistic information display here is based on
1858          * the last statistics notification from uCode
1859          * might not reflect the current uCode activity
1860          */
1861         bt = &priv->statistics.bt_activity;
1862         accum_bt = &priv->accum_stats.bt_activity;
1863
1864         pos += iwl_statistics_flag(priv, buf, bufsz);
1865         pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n");
1866         pos += scnprintf(buf + pos, bufsz - pos,
1867                         "\t\t\tcurrent\t\t\taccumulative\n");
1868         pos += scnprintf(buf + pos, bufsz - pos,
1869                          "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",
1870                          le32_to_cpu(bt->hi_priority_tx_req_cnt),
1871                          accum_bt->hi_priority_tx_req_cnt);
1872         pos += scnprintf(buf + pos, bufsz - pos,
1873                          "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n",
1874                          le32_to_cpu(bt->hi_priority_tx_denied_cnt),
1875                          accum_bt->hi_priority_tx_denied_cnt);
1876         pos += scnprintf(buf + pos, bufsz - pos,
1877                          "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",
1878                          le32_to_cpu(bt->lo_priority_tx_req_cnt),
1879                          accum_bt->lo_priority_tx_req_cnt);
1880         pos += scnprintf(buf + pos, bufsz - pos,
1881                          "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n",
1882                          le32_to_cpu(bt->lo_priority_tx_denied_cnt),
1883                          accum_bt->lo_priority_tx_denied_cnt);
1884         pos += scnprintf(buf + pos, bufsz - pos,
1885                          "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",
1886                          le32_to_cpu(bt->hi_priority_rx_req_cnt),
1887                          accum_bt->hi_priority_rx_req_cnt);
1888         pos += scnprintf(buf + pos, bufsz - pos,
1889                          "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
1890                          le32_to_cpu(bt->hi_priority_rx_denied_cnt),
1891                          accum_bt->hi_priority_rx_denied_cnt);
1892         pos += scnprintf(buf + pos, bufsz - pos,
1893                          "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",
1894                          le32_to_cpu(bt->lo_priority_rx_req_cnt),
1895                          accum_bt->lo_priority_rx_req_cnt);
1896         pos += scnprintf(buf + pos, bufsz - pos,
1897                          "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
1898                          le32_to_cpu(bt->lo_priority_rx_denied_cnt),
1899                          accum_bt->lo_priority_rx_denied_cnt);
1900
1901         pos += scnprintf(buf + pos, bufsz - pos,
1902                          "(rx)num_bt_kills:\t\t%u\t\t\t%u\n",
1903                          le32_to_cpu(priv->statistics.num_bt_kills),
1904                          priv->statistics.accum_num_bt_kills);
1905
1906         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1907         kfree(buf);
1908         return ret;
1909 }
1910
1911 static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
1912                                         char __user *user_buf,
1913                                         size_t count, loff_t *ppos)
1914 {
1915         struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1916         int pos = 0;
1917         char *buf;
1918         int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) +
1919                 (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
1920         ssize_t ret;
1921
1922         if (!iwl_is_alive(priv))
1923                 return -EAGAIN;
1924
1925         buf = kzalloc(bufsz, GFP_KERNEL);
1926         if (!buf) {
1927                 IWL_ERR(priv, "Can not allocate Buffer\n");
1928                 return -ENOMEM;
1929         }
1930
1931         pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n");
1932         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",
1933                          iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),
1934                          priv->reply_tx_stats.pp_delay);
1935         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1936                          iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),
1937                          priv->reply_tx_stats.pp_few_bytes);
1938         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1939                          iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),
1940                          priv->reply_tx_stats.pp_bt_prio);
1941         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1942                          iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),
1943                          priv->reply_tx_stats.pp_quiet_period);
1944         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1945                          iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),
1946                          priv->reply_tx_stats.pp_calc_ttak);
1947         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
1948                          iwl_get_tx_fail_reason(
1949                                 TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),
1950                          priv->reply_tx_stats.int_crossed_retry);
1951         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1952                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),
1953                          priv->reply_tx_stats.short_limit);
1954         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1955                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),
1956                          priv->reply_tx_stats.long_limit);
1957         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1958                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),
1959                          priv->reply_tx_stats.fifo_underrun);
1960         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1961                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),
1962                          priv->reply_tx_stats.drain_flow);
1963         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1964                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),
1965                          priv->reply_tx_stats.rfkill_flush);
1966         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1967                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),
1968                          priv->reply_tx_stats.life_expire);
1969         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1970                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),
1971                          priv->reply_tx_stats.dest_ps);
1972         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1973                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),
1974                          priv->reply_tx_stats.host_abort);
1975         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1976                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),
1977                          priv->reply_tx_stats.pp_delay);
1978         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1979                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),
1980                          priv->reply_tx_stats.sta_invalid);
1981         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1982                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),
1983                          priv->reply_tx_stats.frag_drop);
1984         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1985                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),
1986                          priv->reply_tx_stats.tid_disable);
1987         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1988                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),
1989                          priv->reply_tx_stats.fifo_flush);
1990         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
1991                          iwl_get_tx_fail_reason(
1992                                 TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),
1993                          priv->reply_tx_stats.insuff_cf_poll);
1994         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
1995                          iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX),
1996                          priv->reply_tx_stats.fail_hw_drop);
1997         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
1998                          iwl_get_tx_fail_reason(
1999                                 TX_STATUS_FAIL_NO_BEACON_ON_RADAR),
2000                          priv->reply_tx_stats.sta_color_mismatch);
2001         pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
2002                          priv->reply_tx_stats.unknown);
2003
2004         pos += scnprintf(buf + pos, bufsz - pos,
2005                          "\nStatistics_Agg_TX_Error:\n");
2006
2007         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2008                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK),
2009                          priv->reply_agg_tx_stats.underrun);
2010         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2011                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK),
2012                          priv->reply_agg_tx_stats.bt_prio);
2013         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2014                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK),
2015                          priv->reply_agg_tx_stats.few_bytes);
2016         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2017                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK),
2018                          priv->reply_agg_tx_stats.abort);
2019         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
2020                          iwl_get_agg_tx_fail_reason(
2021                                 AGG_TX_STATE_LAST_SENT_TTL_MSK),
2022                          priv->reply_agg_tx_stats.last_sent_ttl);
2023         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
2024                          iwl_get_agg_tx_fail_reason(
2025                                 AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK),
2026                          priv->reply_agg_tx_stats.last_sent_try);
2027         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
2028                          iwl_get_agg_tx_fail_reason(
2029                                 AGG_TX_STATE_LAST_SENT_BT_KILL_MSK),
2030                          priv->reply_agg_tx_stats.last_sent_bt_kill);
2031         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2032                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK),
2033                          priv->reply_agg_tx_stats.scd_query);
2034         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
2035                          iwl_get_agg_tx_fail_reason(
2036                                 AGG_TX_STATE_TEST_BAD_CRC32_MSK),
2037                          priv->reply_agg_tx_stats.bad_crc32);
2038         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2039                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK),
2040                          priv->reply_agg_tx_stats.response);
2041         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2042                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK),
2043                          priv->reply_agg_tx_stats.dump_tx);
2044         pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
2045                          iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK),
2046                          priv->reply_agg_tx_stats.delay_tx);
2047         pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
2048                          priv->reply_agg_tx_stats.unknown);
2049
2050         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2051         kfree(buf);
2052         return ret;
2053 }
2054
2055 static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
2056                                         char __user *user_buf,
2057                                         size_t count, loff_t *ppos) {
2058
2059         struct iwl_priv *priv = file->private_data;
2060         int pos = 0;
2061         int cnt = 0;
2062         char *buf;
2063         int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
2064         ssize_t ret;
2065         struct iwl_sensitivity_data *data;
2066
2067         data = &priv->sensitivity_data;
2068         buf = kzalloc(bufsz, GFP_KERNEL);
2069         if (!buf) {
2070                 IWL_ERR(priv, "Can not allocate Buffer\n");
2071                 return -ENOMEM;
2072         }
2073
2074         pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
2075                         data->auto_corr_ofdm);
2076         pos += scnprintf(buf + pos, bufsz - pos,
2077                         "auto_corr_ofdm_mrc:\t\t %u\n",
2078                         data->auto_corr_ofdm_mrc);
2079         pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
2080                         data->auto_corr_ofdm_x1);
2081         pos += scnprintf(buf + pos, bufsz - pos,
2082                         "auto_corr_ofdm_mrc_x1:\t\t %u\n",
2083                         data->auto_corr_ofdm_mrc_x1);
2084         pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
2085                         data->auto_corr_cck);
2086         pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
2087                         data->auto_corr_cck_mrc);
2088         pos += scnprintf(buf + pos, bufsz - pos,
2089                         "last_bad_plcp_cnt_ofdm:\t\t %u\n",
2090                         data->last_bad_plcp_cnt_ofdm);
2091         pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
2092                         data->last_fa_cnt_ofdm);
2093         pos += scnprintf(buf + pos, bufsz - pos,
2094                         "last_bad_plcp_cnt_cck:\t\t %u\n",
2095                         data->last_bad_plcp_cnt_cck);
2096         pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
2097                         data->last_fa_cnt_cck);
2098         pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
2099                         data->nrg_curr_state);
2100         pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
2101                         data->nrg_prev_state);
2102         pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
2103         for (cnt = 0; cnt < 10; cnt++) {
2104                 pos += scnprintf(buf + pos, bufsz - pos, " %u",
2105                                 data->nrg_value[cnt]);
2106         }
2107         pos += scnprintf(buf + pos, bufsz - pos, "\n");
2108         pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
2109         for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
2110                 pos += scnprintf(buf + pos, bufsz - pos, " %u",
2111                                 data->nrg_silence_rssi[cnt]);
2112         }
2113         pos += scnprintf(buf + pos, bufsz - pos, "\n");
2114         pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
2115                         data->nrg_silence_ref);
2116         pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
2117                         data->nrg_energy_idx);
2118         pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
2119                         data->nrg_silence_idx);
2120         pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
2121                         data->nrg_th_cck);
2122         pos += scnprintf(buf + pos, bufsz - pos,
2123                         "nrg_auto_corr_silence_diff:\t %u\n",
2124                         data->nrg_auto_corr_silence_diff);
2125         pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
2126                         data->num_in_cck_no_fa);
2127         pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
2128                         data->nrg_th_ofdm);
2129
2130         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2131         kfree(buf);
2132         return ret;
2133 }
2134
2135
2136 static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
2137                                         char __user *user_buf,
2138                                         size_t count, loff_t *ppos) {
2139
2140         struct iwl_priv *priv = file->private_data;
2141         int pos = 0;
2142         int cnt = 0;
2143         char *buf;
2144         int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
2145         ssize_t ret;
2146         struct iwl_chain_noise_data *data;
2147
2148         data = &priv->chain_noise_data;
2149         buf = kzalloc(bufsz, GFP_KERNEL);
2150         if (!buf) {
2151                 IWL_ERR(priv, "Can not allocate Buffer\n");
2152                 return -ENOMEM;
2153         }
2154
2155         pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
2156                         data->active_chains);
2157         pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
2158                         data->chain_noise_a);
2159         pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
2160                         data->chain_noise_b);
2161         pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
2162                         data->chain_noise_c);
2163         pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
2164                         data->chain_signal_a);
2165         pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
2166                         data->chain_signal_b);
2167         pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
2168                         data->chain_signal_c);
2169         pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
2170                         data->beacon_count);
2171
2172         pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
2173         for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
2174                 pos += scnprintf(buf + pos, bufsz - pos, " %u",
2175                                 data->disconn_array[cnt]);
2176         }
2177         pos += scnprintf(buf + pos, bufsz - pos, "\n");
2178         pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
2179         for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
2180                 pos += scnprintf(buf + pos, bufsz - pos, " %u",
2181                                 data->delta_gain_code[cnt]);
2182         }
2183         pos += scnprintf(buf + pos, bufsz - pos, "\n");
2184         pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
2185                         data->radio_write);
2186         pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
2187                         data->state);
2188
2189         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2190         kfree(buf);
2191         return ret;
2192 }
2193
2194 static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
2195                                                     char __user *user_buf,
2196                                                     size_t count, loff_t *ppos)
2197 {
2198         struct iwl_priv *priv = file->private_data;
2199         char buf[60];
2200         int pos = 0;
2201         const size_t bufsz = sizeof(buf);
2202         u32 pwrsave_status;
2203
2204         pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
2205                         CSR_GP_REG_POWER_SAVE_STATUS_MSK;
2206
2207         pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
2208         pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
2209                 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
2210                 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
2211                 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
2212                 "error");
2213
2214         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2215 }
2216
2217 static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
2218                                          const char __user *user_buf,
2219                                          size_t count, loff_t *ppos)
2220 {
2221         struct iwl_priv *priv = file->private_data;
2222         char buf[8];
2223         int buf_size;
2224         int clear;
2225
2226         memset(buf, 0, sizeof(buf));
2227         buf_size = min(count, sizeof(buf) -  1);
2228         if (copy_from_user(buf, user_buf, buf_size))
2229                 return -EFAULT;
2230         if (sscanf(buf, "%d", &clear) != 1)
2231                 return -EFAULT;
2232
2233         /* make request to uCode to retrieve statistics information */
2234         mutex_lock(&priv->mutex);
2235         iwl_send_statistics_request(priv, CMD_SYNC, true);
2236         mutex_unlock(&priv->mutex);
2237
2238         return count;
2239 }
2240
2241 static ssize_t iwl_dbgfs_csr_write(struct file *file,
2242                                          const char __user *user_buf,
2243                                          size_t count, loff_t *ppos)
2244 {
2245         struct iwl_priv *priv = file->private_data;
2246         char buf[8];
2247         int buf_size;
2248         int csr;
2249
2250         memset(buf, 0, sizeof(buf));
2251         buf_size = min(count, sizeof(buf) -  1);
2252         if (copy_from_user(buf, user_buf, buf_size))
2253                 return -EFAULT;
2254         if (sscanf(buf, "%d", &csr) != 1)
2255                 return -EFAULT;
2256
2257         iwl_dump_csr(priv);
2258
2259         return count;
2260 }
2261
2262 static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
2263                                         char __user *user_buf,
2264                                         size_t count, loff_t *ppos) {
2265
2266         struct iwl_priv *priv = file->private_data;
2267         int pos = 0;
2268         char buf[128];
2269         const size_t bufsz = sizeof(buf);
2270
2271         pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
2272                         priv->event_log.ucode_trace ? "On" : "Off");
2273         pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
2274                         priv->event_log.non_wraps_count);
2275         pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
2276                         priv->event_log.wraps_once_count);
2277         pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
2278                         priv->event_log.wraps_more_count);
2279
2280         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2281 }
2282
2283 static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
2284                                          const char __user *user_buf,
2285                                          size_t count, loff_t *ppos)
2286 {
2287         struct iwl_priv *priv = file->private_data;
2288         char buf[8];
2289         int buf_size;
2290         int trace;
2291
2292         memset(buf, 0, sizeof(buf));
2293         buf_size = min(count, sizeof(buf) -  1);
2294         if (copy_from_user(buf, user_buf, buf_size))
2295                 return -EFAULT;
2296         if (sscanf(buf, "%d", &trace) != 1)
2297                 return -EFAULT;
2298
2299         if (trace) {
2300                 priv->event_log.ucode_trace = true;
2301                 /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
2302                 mod_timer(&priv->ucode_trace,
2303                         jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
2304         } else {
2305                 priv->event_log.ucode_trace = false;
2306                 del_timer_sync(&priv->ucode_trace);
2307         }
2308
2309         return count;
2310 }
2311
2312 static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
2313                                          char __user *user_buf,
2314                                          size_t count, loff_t *ppos) {
2315
2316         struct iwl_priv *priv = file->private_data;
2317         int len = 0;
2318         char buf[20];
2319
2320         len = sprintf(buf, "0x%04X\n",
2321                 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
2322         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2323 }
2324
2325 static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
2326                                                 char __user *user_buf,
2327                                                 size_t count, loff_t *ppos) {
2328
2329         struct iwl_priv *priv = file->private_data;
2330         int len = 0;
2331         char buf[20];
2332
2333         len = sprintf(buf, "0x%04X\n",
2334                 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
2335         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2336 }
2337
2338 static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
2339                                          char __user *user_buf,
2340                                          size_t count, loff_t *ppos)
2341 {
2342         struct iwl_priv *priv = file->private_data;
2343         char *buf;
2344         int pos = 0;
2345         ssize_t ret = -EFAULT;
2346
2347         ret = pos = iwl_dump_fh(priv, &buf, true);
2348         if (buf) {
2349                 ret = simple_read_from_buffer(user_buf,
2350                                               count, ppos, buf, pos);
2351                 kfree(buf);
2352         }
2353
2354         return ret;
2355 }
2356
2357 static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,
2358                                         char __user *user_buf,
2359                                         size_t count, loff_t *ppos) {
2360
2361         struct iwl_priv *priv = file->private_data;
2362         int pos = 0;
2363         char buf[12];
2364         const size_t bufsz = sizeof(buf);
2365
2366         pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
2367                         priv->missed_beacon_threshold);
2368
2369         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2370 }
2371
2372 static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,
2373                                          const char __user *user_buf,
2374                                          size_t count, loff_t *ppos)
2375 {
2376         struct iwl_priv *priv = file->private_data;
2377         char buf[8];
2378         int buf_size;
2379         int missed;
2380
2381         memset(buf, 0, sizeof(buf));
2382         buf_size = min(count, sizeof(buf) -  1);
2383         if (copy_from_user(buf, user_buf, buf_size))
2384                 return -EFAULT;
2385         if (sscanf(buf, "%d", &missed) != 1)
2386                 return -EINVAL;
2387
2388         if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
2389             missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
2390                 priv->missed_beacon_threshold =
2391                         IWL_MISSED_BEACON_THRESHOLD_DEF;
2392         else
2393                 priv->missed_beacon_threshold = missed;
2394
2395         return count;
2396 }
2397
2398 static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
2399                                         char __user *user_buf,
2400                                         size_t count, loff_t *ppos) {
2401
2402         struct iwl_priv *priv = file->private_data;
2403         int pos = 0;
2404         char buf[12];
2405         const size_t bufsz = sizeof(buf);
2406
2407         pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
2408                         priv->cfg->base_params->plcp_delta_threshold);
2409
2410         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2411 }
2412
2413 static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
2414                                         const char __user *user_buf,
2415                                         size_t count, loff_t *ppos) {
2416
2417         struct iwl_priv *priv = file->private_data;
2418         char buf[8];
2419         int buf_size;
2420         int plcp;
2421
2422         memset(buf, 0, sizeof(buf));
2423         buf_size = min(count, sizeof(buf) -  1);
2424         if (copy_from_user(buf, user_buf, buf_size))
2425                 return -EFAULT;
2426         if (sscanf(buf, "%d", &plcp) != 1)
2427                 return -EINVAL;
2428         if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
2429                 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
2430                 priv->cfg->base_params->plcp_delta_threshold =
2431                         IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
2432         else
2433                 priv->cfg->base_params->plcp_delta_threshold = plcp;
2434         return count;
2435 }
2436
2437 static ssize_t iwl_dbgfs_force_reset_read(struct file *file,
2438                                         char __user *user_buf,
2439                                         size_t count, loff_t *ppos) {
2440
2441         struct iwl_priv *priv = file->private_data;
2442         int i, pos = 0;
2443         char buf[300];
2444         const size_t bufsz = sizeof(buf);
2445         struct iwl_force_reset *force_reset;
2446
2447         for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
2448                 force_reset = &priv->force_reset[i];
2449                 pos += scnprintf(buf + pos, bufsz - pos,
2450                                 "Force reset method %d\n", i);
2451                 pos += scnprintf(buf + pos, bufsz - pos,
2452                                 "\tnumber of reset request: %d\n",
2453                                 force_reset->reset_request_count);
2454                 pos += scnprintf(buf + pos, bufsz - pos,
2455                                 "\tnumber of reset request success: %d\n",
2456                                 force_reset->reset_success_count);
2457                 pos += scnprintf(buf + pos, bufsz - pos,
2458                                 "\tnumber of reset request reject: %d\n",
2459                                 force_reset->reset_reject_count);
2460                 pos += scnprintf(buf + pos, bufsz - pos,
2461                                 "\treset duration: %lu\n",
2462                                 force_reset->reset_duration);
2463         }
2464         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2465 }
2466
2467 static ssize_t iwl_dbgfs_force_reset_write(struct file *file,
2468                                         const char __user *user_buf,
2469                                         size_t count, loff_t *ppos) {
2470
2471         struct iwl_priv *priv = file->private_data;
2472         char buf[8];
2473         int buf_size;
2474         int reset, ret;
2475
2476         memset(buf, 0, sizeof(buf));
2477         buf_size = min(count, sizeof(buf) -  1);
2478         if (copy_from_user(buf, user_buf, buf_size))
2479                 return -EFAULT;
2480         if (sscanf(buf, "%d", &reset) != 1)
2481                 return -EINVAL;
2482         switch (reset) {
2483         case IWL_RF_RESET:
2484         case IWL_FW_RESET:
2485                 ret = iwl_force_reset(priv, reset, true);
2486                 break;
2487         default:
2488                 return -EINVAL;
2489         }
2490         return ret ? ret : count;
2491 }
2492
2493 static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
2494                                         const char __user *user_buf,
2495                                         size_t count, loff_t *ppos) {
2496
2497         struct iwl_priv *priv = file->private_data;
2498         char buf[8];
2499         int buf_size;
2500         int flush;
2501
2502         memset(buf, 0, sizeof(buf));
2503         buf_size = min(count, sizeof(buf) -  1);
2504         if (copy_from_user(buf, user_buf, buf_size))
2505                 return -EFAULT;
2506         if (sscanf(buf, "%d", &flush) != 1)
2507                 return -EINVAL;
2508
2509         if (iwl_is_rfkill(priv))
2510                 return -EFAULT;
2511
2512         iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
2513
2514         return count;
2515 }
2516
2517 static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
2518                                         const char __user *user_buf,
2519                                         size_t count, loff_t *ppos) {
2520
2521         struct iwl_priv *priv = file->private_data;
2522         char buf[8];
2523         int buf_size;
2524         int timeout;
2525
2526         memset(buf, 0, sizeof(buf));
2527         buf_size = min(count, sizeof(buf) -  1);
2528         if (copy_from_user(buf, user_buf, buf_size))
2529                 return -EFAULT;
2530         if (sscanf(buf, "%d", &timeout) != 1)
2531                 return -EINVAL;
2532         if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
2533                 timeout = IWL_DEF_WD_TIMEOUT;
2534
2535         priv->cfg->base_params->wd_timeout = timeout;
2536         iwl_setup_watchdog(priv);
2537         return count;
2538 }
2539
2540 static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file,
2541                                         char __user *user_buf,
2542                                         size_t count, loff_t *ppos) {
2543
2544         struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
2545         int pos = 0;
2546         char buf[200];
2547         const size_t bufsz = sizeof(buf);
2548
2549         if (!priv->bt_enable_flag) {
2550                 pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n");
2551                 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2552         }
2553         pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n",
2554                 priv->bt_enable_flag);
2555         pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n",
2556                 priv->bt_full_concurrent ? "full concurrency" : "3-wire");
2557         pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, "
2558                          "last traffic notif: %d\n",
2559                 priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load);
2560         pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, "
2561                          "kill_ack_mask: %x, kill_cts_mask: %x\n",
2562                 priv->bt_ch_announce, priv->kill_ack_mask,
2563                 priv->kill_cts_mask);
2564
2565         pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: ");
2566         switch (priv->bt_traffic_load) {
2567         case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
2568                 pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n");
2569                 break;
2570         case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
2571                 pos += scnprintf(buf + pos, bufsz - pos, "High\n");
2572                 break;
2573         case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
2574                 pos += scnprintf(buf + pos, bufsz - pos, "Low\n");
2575                 break;
2576         case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
2577         default:
2578                 pos += scnprintf(buf + pos, bufsz - pos, "None\n");
2579                 break;
2580         }
2581
2582         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2583 }
2584
2585 static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
2586                                         char __user *user_buf,
2587                                         size_t count, loff_t *ppos)
2588 {
2589         struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
2590
2591         int pos = 0;
2592         char buf[40];
2593         const size_t bufsz = sizeof(buf);
2594
2595         if (priv->cfg->ht_params)
2596                 pos += scnprintf(buf + pos, bufsz - pos,
2597                          "use %s for aggregation\n",
2598                          (priv->cfg->ht_params->use_rts_for_aggregation) ?
2599                                 "rts/cts" : "cts-to-self");
2600         else
2601                 pos += scnprintf(buf + pos, bufsz - pos, "N/A");
2602
2603         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2604 }
2605
2606 static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
2607                                         const char __user *user_buf,
2608                                         size_t count, loff_t *ppos) {
2609
2610         struct iwl_priv *priv = file->private_data;
2611         char buf[8];
2612         int buf_size;
2613         int rts;
2614
2615         if (!priv->cfg->ht_params)
2616                 return -EINVAL;
2617
2618         memset(buf, 0, sizeof(buf));
2619         buf_size = min(count, sizeof(buf) -  1);
2620         if (copy_from_user(buf, user_buf, buf_size))
2621                 return -EFAULT;
2622         if (sscanf(buf, "%d", &rts) != 1)
2623                 return -EINVAL;
2624         if (rts)
2625                 priv->cfg->ht_params->use_rts_for_aggregation = true;
2626         else
2627                 priv->cfg->ht_params->use_rts_for_aggregation = false;
2628         return count;
2629 }
2630
2631 DEBUGFS_READ_FILE_OPS(rx_statistics);
2632 DEBUGFS_READ_FILE_OPS(tx_statistics);
2633 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
2634 DEBUGFS_READ_FILE_OPS(rx_queue);
2635 DEBUGFS_READ_FILE_OPS(tx_queue);
2636 DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
2637 DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
2638 DEBUGFS_READ_FILE_OPS(ucode_general_stats);
2639 DEBUGFS_READ_FILE_OPS(sensitivity);
2640 DEBUGFS_READ_FILE_OPS(chain_noise);
2641 DEBUGFS_READ_FILE_OPS(power_save_status);
2642 DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
2643 DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
2644 DEBUGFS_WRITE_FILE_OPS(csr);
2645 DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
2646 DEBUGFS_READ_FILE_OPS(fh_reg);
2647 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
2648 DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
2649 DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
2650 DEBUGFS_READ_FILE_OPS(rxon_flags);
2651 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
2652 DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
2653 DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
2654 DEBUGFS_WRITE_FILE_OPS(wd_timeout);
2655 DEBUGFS_READ_FILE_OPS(bt_traffic);
2656 DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
2657 DEBUGFS_READ_FILE_OPS(reply_tx_error);
2658
2659 /*
2660  * Create the debugfs files and directories
2661  *
2662  */
2663 int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
2664 {
2665         struct dentry *phyd = priv->hw->wiphy->debugfsdir;
2666         struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
2667
2668         dir_drv = debugfs_create_dir(name, phyd);
2669         if (!dir_drv)
2670                 return -ENOMEM;
2671
2672         priv->debugfs_dir = dir_drv;
2673
2674         dir_data = debugfs_create_dir("data", dir_drv);
2675         if (!dir_data)
2676                 goto err;
2677         dir_rf = debugfs_create_dir("rf", dir_drv);
2678         if (!dir_rf)
2679                 goto err;
2680         dir_debug = debugfs_create_dir("debug", dir_drv);
2681         if (!dir_debug)
2682                 goto err;
2683
2684         DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
2685         DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
2686         DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR);
2687         DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
2688         DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
2689         DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
2690         DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
2691         DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
2692         DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
2693         DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
2694         DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
2695         DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
2696         DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
2697         DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
2698         DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
2699         DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
2700         DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
2701         DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
2702         DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
2703         DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
2704         DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
2705         DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR);
2706         DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
2707         DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
2708         DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
2709         DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
2710         DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
2711         DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
2712         DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
2713         DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
2714         DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
2715
2716         DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
2717         DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
2718         DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
2719         DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
2720         DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
2721         DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
2722         DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
2723         DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
2724         if (iwl_advanced_bt_coexist(priv))
2725                 DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
2726         DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
2727                          &priv->disable_sens_cal);
2728         DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
2729                          &priv->disable_chain_noise_cal);
2730         return 0;
2731
2732 err:
2733         IWL_ERR(priv, "Can't create the debugfs directory\n");
2734         iwl_dbgfs_unregister(priv);
2735         return -ENOMEM;
2736 }
2737
2738 /**
2739  * Remove the debugfs files and directories
2740  *
2741  */
2742 void iwl_dbgfs_unregister(struct iwl_priv *priv)
2743 {
2744         if (!priv->debugfs_dir)
2745                 return;
2746
2747         debugfs_remove_recursive(priv->debugfs_dir);
2748         priv->debugfs_dir = NULL;
2749 }
2750
2751
2752