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