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