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