iwlegacy: gather all 4965 handlers in one place
[linux-block.git] / drivers / net / wireless / iwlegacy / debug.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>
515db093 29#include <linux/export.h>
be663ab6
WYG
30#include <net/mac80211.h>
31
98613be0 32#include "common.h"
be663ab6
WYG
33
34/* create and remove of files */
35#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
46bc8d4b 36 if (!debugfs_create_file(#name, mode, parent, il, \
e2ebc833 37 &il_dbgfs_##name##_ops)) \
be663ab6
WYG
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) \
e2ebc833 59static ssize_t il_dbgfs_##name##_read(struct file *file, \
be663ab6
WYG
60 char __user *user_buf, \
61 size_t count, loff_t *ppos);
62
63#define DEBUGFS_WRITE_FUNC(name) \
e2ebc833 64static ssize_t il_dbgfs_##name##_write(struct file *file, \
be663ab6
WYG
65 const char __user *user_buf, \
66 size_t count, loff_t *ppos);
67
be663ab6 68static int
e2ebc833 69il_dbgfs_open_file_generic(struct inode *inode, struct file *file)
be663ab6
WYG
70{
71 file->private_data = inode->i_private;
72 return 0;
73}
74
1722f8e1
SG
75#define DEBUGFS_READ_FILE_OPS(name) \
76 DEBUGFS_READ_FUNC(name); \
e2ebc833
SG
77static const struct file_operations il_dbgfs_##name##_ops = { \
78 .read = il_dbgfs_##name##_read, \
1722f8e1
SG
79 .open = il_dbgfs_open_file_generic, \
80 .llseek = generic_file_llseek, \
be663ab6
WYG
81};
82
1722f8e1
SG
83#define DEBUGFS_WRITE_FILE_OPS(name) \
84 DEBUGFS_WRITE_FUNC(name); \
e2ebc833
SG
85static const struct file_operations il_dbgfs_##name##_ops = { \
86 .write = il_dbgfs_##name##_write, \
1722f8e1
SG
87 .open = il_dbgfs_open_file_generic, \
88 .llseek = generic_file_llseek, \
be663ab6
WYG
89};
90
1722f8e1
SG
91#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
92 DEBUGFS_READ_FUNC(name); \
93 DEBUGFS_WRITE_FUNC(name); \
e2ebc833
SG
94static 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, \
1722f8e1 98 .llseek = generic_file_llseek, \
be663ab6
WYG
99};
100
e7392364 101static ssize_t
1722f8e1
SG
102il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count,
103 loff_t *ppos)
e7392364 104{
be663ab6 105
46bc8d4b 106 struct il_priv *il = file->private_data;
be663ab6
WYG
107 char *buf;
108 int pos = 0;
109
110 int cnt;
111 ssize_t ret;
e7392364
SG
112 const size_t bufsz =
113 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
be663ab6
WYG
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++) {
e7392364
SG
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]);
be663ab6
WYG
122 }
123 pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
124 for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
e7392364
SG
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]);
be663ab6
WYG
128 }
129 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
e7392364
SG
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);
be663ab6
WYG
136 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
137 kfree(buf);
138 return ret;
139}
140
141static ssize_t
ebf0d90d 142il_dbgfs_clear_traffic_stats_write(struct file *file,
1722f8e1
SG
143 const char __user *user_buf, size_t count,
144 loff_t *ppos)
be663ab6 145{
46bc8d4b 146 struct il_priv *il = file->private_data;
be663ab6
WYG
147 u32 clear_flag;
148 char buf[8];
149 int buf_size;
150
151 memset(buf, 0, sizeof(buf));
e7392364 152 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
153 if (copy_from_user(buf, user_buf, buf_size))
154 return -EFAULT;
155 if (sscanf(buf, "%x", &clear_flag) != 1)
156 return -EFAULT;
46bc8d4b 157 il_clear_traffic_stats(il);
be663ab6
WYG
158
159 return count;
160}
161
e7392364 162static ssize_t
1722f8e1
SG
163il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count,
164 loff_t *ppos)
e7392364 165{
be663ab6 166
46bc8d4b 167 struct il_priv *il = file->private_data;
be663ab6
WYG
168 char *buf;
169 int pos = 0;
170 int cnt;
171 ssize_t ret;
e7392364
SG
172 const size_t bufsz =
173 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
be663ab6
WYG
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++) {
e7392364
SG
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]);
be663ab6
WYG
183 }
184 pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
185 for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
e7392364
SG
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]);
be663ab6
WYG
189 }
190 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
e7392364
SG
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);
be663ab6
WYG
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;
e7392364 206static ssize_t
1722f8e1
SG
207il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count,
208 loff_t *ppos)
be663ab6
WYG
209{
210 u32 val;
211 char *buf;
212 ssize_t ret;
213 int i;
214 int pos = 0;
46bc8d4b 215 struct il_priv *il = file->private_data;
be663ab6
WYG
216 size_t bufsz;
217
218 /* default is to dump the entire data segment */
46bc8d4b
SG
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;
be663ab6 223 else
46bc8d4b 224 il->dbgfs_sram_len = il->ucode_data.len;
be663ab6 225 }
e7392364 226 bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10;
be663ab6
WYG
227 buf = kmalloc(bufsz, GFP_KERNEL);
228 if (!buf)
229 return -ENOMEM;
e7392364
SG
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);
46bc8d4b 236 for (i = il->dbgfs_sram_len; i > 0; i -= 4) {
e7392364
SG
237 val =
238 il_read_targ_mem(il,
239 il->dbgfs_sram_offset +
240 il->dbgfs_sram_len - i);
be663ab6
WYG
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
e7392364 265static ssize_t
1722f8e1
SG
266il_dbgfs_sram_write(struct file *file, const char __user *user_buf,
267 size_t count, loff_t *ppos)
be663ab6 268{
46bc8d4b 269 struct il_priv *il = file->private_data;
be663ab6
WYG
270 char buf[64];
271 int buf_size;
272 u32 offset, len;
273
274 memset(buf, 0, sizeof(buf));
e7392364 275 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
276 if (copy_from_user(buf, user_buf, buf_size))
277 return -EFAULT;
278
279 if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
46bc8d4b
SG
280 il->dbgfs_sram_offset = offset;
281 il->dbgfs_sram_len = len;
be663ab6 282 } else {
46bc8d4b
SG
283 il->dbgfs_sram_offset = 0;
284 il->dbgfs_sram_len = 0;
be663ab6
WYG
285 }
286
287 return count;
288}
289
290static ssize_t
1722f8e1
SG
291il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count,
292 loff_t *ppos)
be663ab6 293{
46bc8d4b 294 struct il_priv *il = file->private_data;
e2ebc833 295 struct il_station_entry *station;
46bc8d4b 296 int max_sta = il->hw_params.max_stations;
be663ab6
WYG
297 char *buf;
298 int i, j, pos = 0;
299 ssize_t ret;
300 /* Add 30 for initial string */
46bc8d4b 301 const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations);
be663ab6
WYG
302
303 buf = kmalloc(bufsz, GFP_KERNEL);
304 if (!buf)
305 return -ENOMEM;
306
e7392364
SG
307 pos +=
308 scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
309 il->num_stations);
be663ab6
WYG
310
311 for (i = 0; i < max_sta; i++) {
46bc8d4b 312 station = &il->stations[i];
be663ab6
WYG
313 if (!station->used)
314 continue;
e7392364
SG
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");
be663ab6
WYG
326
327 for (j = 0; j < MAX_TID_COUNT; j++) {
e7392364
SG
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);
be663ab6
WYG
338
339 if (station->tid[j].agg.wait_for_ba)
e7392364
SG
340 pos +=
341 scnprintf(buf + pos, bufsz - pos,
342 " - waitforba");
be663ab6
WYG
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
e7392364 354static ssize_t
1722f8e1
SG
355il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
356 loff_t *ppos)
be663ab6
WYG
357{
358 ssize_t ret;
46bc8d4b 359 struct il_priv *il = file->private_data;
be663ab6
WYG
360 int pos = 0, ofs = 0, buf_size = 0;
361 const u8 *ptr;
362 char *buf;
363 u16 eeprom_ver;
89ef1ed2 364 size_t eeprom_len = il->cfg->eeprom_size;
be663ab6
WYG
365 buf_size = 4 * eeprom_len + 256;
366
367 if (eeprom_len % 16) {
9406f797 368 IL_ERR("NVM size is not multiple of 16.\n");
be663ab6
WYG
369 return -ENODATA;
370 }
371
46bc8d4b 372 ptr = il->eeprom;
be663ab6 373 if (!ptr) {
9406f797 374 IL_ERR("Invalid EEPROM memory\n");
be663ab6
WYG
375 return -ENOMEM;
376 }
377
378 /* 4 characters for byte 0xYY */
379 buf = kzalloc(buf_size, GFP_KERNEL);
380 if (!buf) {
9406f797 381 IL_ERR("Can not allocate Buffer\n");
be663ab6
WYG
382 return -ENOMEM;
383 }
46bc8d4b 384 eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION);
e7392364
SG
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) {
be663ab6 389 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
e7392364 390 hex_dump_to_buffer(ptr + ofs, 16, 16, 2, buf + pos,
be663ab6
WYG
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
be663ab6 402static ssize_t
1722f8e1
SG
403il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
404 loff_t *ppos)
be663ab6 405{
46bc8d4b 406 struct il_priv *il = file->private_data;
be663ab6
WYG
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
a6766ccd 413 if (!test_bit(S_GEO_CONFIGURED, &il->status))
be663ab6
WYG
414 return -EAGAIN;
415
416 buf = kzalloc(bufsz, GFP_KERNEL);
417 if (!buf) {
9406f797 418 IL_ERR("Can not allocate Buffer\n");
be663ab6
WYG
419 return -ENOMEM;
420 }
421
46bc8d4b 422 supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ);
be663ab6
WYG
423 if (supp_band) {
424 channels = supp_band->channels;
425
e7392364
SG
426 pos +=
427 scnprintf(buf + pos, bufsz - pos,
428 "Displaying %d channels in 2.4GHz band 802.11bg):\n",
429 supp_band->n_channels);
be663ab6
WYG
430
431 for (i = 0; i < supp_band->n_channels; i++)
e7392364
SG
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");
be663ab6 448 }
46bc8d4b 449 supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
be663ab6
WYG
450 if (supp_band) {
451 channels = supp_band->channels;
452
e7392364
SG
453 pos +=
454 scnprintf(buf + pos, bufsz - pos,
455 "Displaying %d channels in 5.2GHz band (802.11a)\n",
456 supp_band->n_channels);
be663ab6
WYG
457
458 for (i = 0; i < supp_band->n_channels; i++)
e7392364
SG
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");
be663ab6
WYG
475 }
476 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
477 kfree(buf);
478 return ret;
479}
480
e7392364 481static ssize_t
1722f8e1
SG
482il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count,
483 loff_t *ppos)
e7392364 484{
be663ab6 485
46bc8d4b 486 struct il_priv *il = file->private_data;
be663ab6
WYG
487 char buf[512];
488 int pos = 0;
489 const size_t bufsz = sizeof(buf);
490
e7392364
SG
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));
be663ab6
WYG
539 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
540}
541
e7392364 542static ssize_t
1722f8e1
SG
543il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count,
544 loff_t *ppos)
e7392364 545{
be663ab6 546
46bc8d4b 547 struct il_priv *il = file->private_data;
be663ab6
WYG
548 int pos = 0;
549 int cnt = 0;
550 char *buf;
e7392364 551 int bufsz = 24 * 64; /* 24 items * 64 char per item */
be663ab6
WYG
552 ssize_t ret;
553
554 buf = kzalloc(bufsz, GFP_KERNEL);
555 if (!buf) {
9406f797 556 IL_ERR("Can not allocate Buffer\n");
be663ab6
WYG
557 return -ENOMEM;
558 }
559
e7392364
SG
560 pos +=
561 scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n");
be663ab6 562
e7392364
SG
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);
46bc8d4b 569 if (il->isr_stats.sw || il->isr_stats.hw) {
e7392364
SG
570 pos +=
571 scnprintf(buf + pos, bufsz - pos,
572 "\tLast Restarting Code: 0x%X\n",
573 il->isr_stats.err_code);
be663ab6 574 }
d3175167 575#ifdef CONFIG_IWLEGACY_DEBUG
e7392364
SG
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);
be663ab6 582#endif
e7392364
SG
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);
4d69c752 599 for (cnt = 0; cnt < IL_CN_MAX; cnt++) {
d0c72347 600 if (il->isr_stats.handlers[cnt] > 0)
e7392364
SG
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]);
be663ab6
WYG
606 }
607
e7392364
SG
608 pos +=
609 scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
610 il->isr_stats.tx);
be663ab6 611
e7392364
SG
612 pos +=
613 scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
614 il->isr_stats.unhandled);
be663ab6
WYG
615
616 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
617 kfree(buf);
618 return ret;
619}
620
e7392364 621static ssize_t
1722f8e1
SG
622il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf,
623 size_t count, loff_t *ppos)
be663ab6 624{
46bc8d4b 625 struct il_priv *il = file->private_data;
be663ab6
WYG
626 char buf[8];
627 int buf_size;
628 u32 reset_flag;
629
630 memset(buf, 0, sizeof(buf));
e7392364 631 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
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)
46bc8d4b 637 il_clear_isr_stats(il);
be663ab6
WYG
638
639 return count;
640}
641
642static ssize_t
1722f8e1
SG
643il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count,
644 loff_t *ppos)
be663ab6 645{
46bc8d4b 646 struct il_priv *il = file->private_data;
be663ab6 647 int pos = 0, i;
7c2cde2e 648 char buf[256];
be663ab6
WYG
649 const size_t bufsz = sizeof(buf);
650
17d6e557 651 for (i = 0; i < AC_NUM; i++) {
e7392364
SG
652 pos +=
653 scnprintf(buf + pos, bufsz - pos,
654 "\tcw_min\tcw_max\taifsn\ttxop\n");
655 pos +=
656 scnprintf(buf + pos, bufsz - pos,
657 "AC[%d]\t%u\t%u\t%u\t%u\n", i,
8d44f2bd
SG
658 il->qos_data.def_qos_parm.ac[i].cw_min,
659 il->qos_data.def_qos_parm.ac[i].cw_max,
660 il->qos_data.def_qos_parm.ac[i].aifsn,
661 il->qos_data.def_qos_parm.ac[i].edca_txop);
be663ab6 662 }
17d6e557 663
be663ab6
WYG
664 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
665}
666
e7392364 667static ssize_t
1722f8e1
SG
668il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf,
669 size_t count, loff_t *ppos)
be663ab6 670{
46bc8d4b 671 struct il_priv *il = file->private_data;
be663ab6
WYG
672 char buf[8];
673 int buf_size;
674 int ht40;
675
676 memset(buf, 0, sizeof(buf));
e7392364 677 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
678 if (copy_from_user(buf, user_buf, buf_size))
679 return -EFAULT;
680 if (sscanf(buf, "%d", &ht40) != 1)
681 return -EFAULT;
46bc8d4b
SG
682 if (!il_is_any_associated(il))
683 il->disable_ht40 = ht40 ? true : false;
be663ab6 684 else {
9406f797 685 IL_ERR("Sta associated with AP - "
e7392364 686 "Change to 40MHz channel support is not allowed\n");
be663ab6
WYG
687 return -EINVAL;
688 }
689
690 return count;
691}
692
e7392364 693static ssize_t
1722f8e1
SG
694il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf,
695 size_t count, loff_t *ppos)
be663ab6 696{
46bc8d4b 697 struct il_priv *il = file->private_data;
be663ab6
WYG
698 char buf[100];
699 int pos = 0;
700 const size_t bufsz = sizeof(buf);
701
e7392364
SG
702 pos +=
703 scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n",
704 il->disable_ht40 ? "Disabled" : "Enabled");
be663ab6
WYG
705 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
706}
707
708DEBUGFS_READ_WRITE_FILE_OPS(sram);
be663ab6
WYG
709DEBUGFS_READ_FILE_OPS(nvm);
710DEBUGFS_READ_FILE_OPS(stations);
711DEBUGFS_READ_FILE_OPS(channels);
712DEBUGFS_READ_FILE_OPS(status);
713DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
714DEBUGFS_READ_FILE_OPS(qos);
715DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
716
e7392364 717static ssize_t
1722f8e1
SG
718il_dbgfs_traffic_log_read(struct file *file, char __user *user_buf,
719 size_t count, loff_t *ppos)
be663ab6 720{
46bc8d4b 721 struct il_priv *il = file->private_data;
be663ab6
WYG
722 int pos = 0, ofs = 0;
723 int cnt = 0, entry;
e2ebc833
SG
724 struct il_tx_queue *txq;
725 struct il_queue *q;
46bc8d4b 726 struct il_rx_queue *rxq = &il->rxq;
be663ab6 727 char *buf;
e7392364
SG
728 int bufsz =
729 ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
89ef1ed2 730 (il->cfg->num_of_queues * 32 * 8) + 400;
be663ab6
WYG
731 const u8 *ptr;
732 ssize_t ret;
733
46bc8d4b 734 if (!il->txq) {
9406f797 735 IL_ERR("txq not ready\n");
be663ab6
WYG
736 return -EAGAIN;
737 }
738 buf = kzalloc(bufsz, GFP_KERNEL);
739 if (!buf) {
9406f797 740 IL_ERR("Can not allocate buffer\n");
be663ab6
WYG
741 return -ENOMEM;
742 }
743 pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
46bc8d4b
SG
744 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
745 txq = &il->txq[cnt];
be663ab6 746 q = &txq->q;
e7392364
SG
747 pos +=
748 scnprintf(buf + pos, bufsz - pos,
749 "q[%d]: read_ptr: %u, write_ptr: %u\n", cnt,
750 q->read_ptr, q->write_ptr);
be663ab6 751 }
d2ddf621 752 if (il->tx_traffic && (il_debug_level & IL_DL_TX)) {
46bc8d4b 753 ptr = il->tx_traffic;
e7392364
SG
754 pos +=
755 scnprintf(buf + pos, bufsz - pos, "Tx Traffic idx: %u\n",
756 il->tx_traffic_idx);
e2ebc833
SG
757 for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
758 for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
e7392364
SG
759 entry++, ofs += 16) {
760 pos +=
761 scnprintf(buf + pos, bufsz - pos, "0x%.4x ",
762 ofs);
be663ab6
WYG
763 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
764 buf + pos, bufsz - pos, 0);
765 pos += strlen(buf + pos);
766 if (bufsz - pos > 0)
767 buf[pos++] = '\n';
768 }
769 }
770 }
771
772 pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
e7392364
SG
773 pos +=
774 scnprintf(buf + pos, bufsz - pos, "read: %u, write: %u\n",
775 rxq->read, rxq->write);
be663ab6 776
d2ddf621 777 if (il->rx_traffic && (il_debug_level & IL_DL_RX)) {
46bc8d4b 778 ptr = il->rx_traffic;
e7392364
SG
779 pos +=
780 scnprintf(buf + pos, bufsz - pos, "Rx Traffic idx: %u\n",
781 il->rx_traffic_idx);
e2ebc833
SG
782 for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
783 for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
e7392364
SG
784 entry++, ofs += 16) {
785 pos +=
786 scnprintf(buf + pos, bufsz - pos, "0x%.4x ",
787 ofs);
be663ab6
WYG
788 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
789 buf + pos, bufsz - pos, 0);
790 pos += strlen(buf + pos);
791 if (bufsz - pos > 0)
792 buf[pos++] = '\n';
793 }
794 }
795 }
796
797 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
798 kfree(buf);
799 return ret;
800}
801
e7392364 802static ssize_t
1722f8e1
SG
803il_dbgfs_traffic_log_write(struct file *file, const char __user *user_buf,
804 size_t count, loff_t *ppos)
be663ab6 805{
46bc8d4b 806 struct il_priv *il = file->private_data;
be663ab6
WYG
807 char buf[8];
808 int buf_size;
809 int traffic_log;
810
811 memset(buf, 0, sizeof(buf));
e7392364 812 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
813 if (copy_from_user(buf, user_buf, buf_size))
814 return -EFAULT;
815 if (sscanf(buf, "%d", &traffic_log) != 1)
816 return -EFAULT;
817 if (traffic_log == 0)
46bc8d4b 818 il_reset_traffic_log(il);
be663ab6
WYG
819
820 return count;
821}
822
e7392364 823static ssize_t
1722f8e1
SG
824il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count,
825 loff_t *ppos)
e7392364 826{
be663ab6 827
46bc8d4b 828 struct il_priv *il = file->private_data;
e2ebc833
SG
829 struct il_tx_queue *txq;
830 struct il_queue *q;
be663ab6
WYG
831 char *buf;
832 int pos = 0;
833 int cnt;
834 int ret;
e7392364 835 const size_t bufsz =
89ef1ed2 836 sizeof(char) * 64 * il->cfg->num_of_queues;
be663ab6 837
46bc8d4b 838 if (!il->txq) {
9406f797 839 IL_ERR("txq not ready\n");
be663ab6
WYG
840 return -EAGAIN;
841 }
842 buf = kzalloc(bufsz, GFP_KERNEL);
843 if (!buf)
844 return -ENOMEM;
845
46bc8d4b
SG
846 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
847 txq = &il->txq[cnt];
be663ab6 848 q = &txq->q;
e7392364
SG
849 pos +=
850 scnprintf(buf + pos, bufsz - pos,
851 "hwq %.2d: read=%u write=%u stop=%d"
852 " swq_id=%#.2x (ac %d/hwq %d)\n", cnt,
1722f8e1
SG
853 q->read_ptr, q->write_ptr,
854 !!test_bit(cnt, il->queue_stopped),
e7392364
SG
855 txq->swq_id, txq->swq_id & 3,
856 (txq->swq_id >> 2) & 0x1f);
be663ab6
WYG
857 if (cnt >= 4)
858 continue;
859 /* for the ACs, display the stop count too */
e7392364
SG
860 pos +=
861 scnprintf(buf + pos, bufsz - pos,
862 " stop-count: %d\n",
863 atomic_read(&il->queue_stop_count[cnt]));
be663ab6
WYG
864 }
865 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
866 kfree(buf);
867 return ret;
868}
869
e7392364 870static ssize_t
1722f8e1
SG
871il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count,
872 loff_t *ppos)
e7392364 873{
be663ab6 874
46bc8d4b
SG
875 struct il_priv *il = file->private_data;
876 struct il_rx_queue *rxq = &il->rxq;
be663ab6
WYG
877 char buf[256];
878 int pos = 0;
879 const size_t bufsz = sizeof(buf);
880
e7392364
SG
881 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read);
882 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write);
883 pos +=
884 scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
885 rxq->free_count);
be663ab6 886 if (rxq->rb_stts) {
e7392364
SG
887 pos +=
888 scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
889 le16_to_cpu(rxq->rb_stts->
890 closed_rb_num) & 0x0FFF);
be663ab6 891 } else {
e7392364
SG
892 pos +=
893 scnprintf(buf + pos, bufsz - pos,
894 "closed_rb_num: Not Allocated\n");
be663ab6
WYG
895 }
896 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
897}
898
e7392364 899static ssize_t
1722f8e1
SG
900il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf,
901 size_t count, loff_t *ppos)
be663ab6 902{
46bc8d4b 903 struct il_priv *il = file->private_data;
c39ae9fd 904 return il->ops->lib->debugfs_ops.rx_stats_read(file, user_buf, count, ppos);
be663ab6
WYG
905}
906
e7392364 907static ssize_t
1722f8e1
SG
908il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf,
909 size_t count, loff_t *ppos)
be663ab6 910{
46bc8d4b 911 struct il_priv *il = file->private_data;
c39ae9fd 912 return il->ops->lib->debugfs_ops.tx_stats_read(file, user_buf, count, ppos);
be663ab6
WYG
913}
914
e7392364 915static ssize_t
1722f8e1
SG
916il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf,
917 size_t count, loff_t *ppos)
be663ab6 918{
46bc8d4b 919 struct il_priv *il = file->private_data;
c39ae9fd 920 return il->ops->lib->debugfs_ops.general_stats_read(file, user_buf, count, ppos);
be663ab6
WYG
921}
922
e7392364 923static ssize_t
1722f8e1
SG
924il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf,
925 size_t count, loff_t *ppos)
e7392364 926{
be663ab6 927
46bc8d4b 928 struct il_priv *il = file->private_data;
be663ab6
WYG
929 int pos = 0;
930 int cnt = 0;
931 char *buf;
e2ebc833 932 int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
be663ab6 933 ssize_t ret;
e2ebc833 934 struct il_sensitivity_data *data;
be663ab6 935
46bc8d4b 936 data = &il->sensitivity_data;
be663ab6
WYG
937 buf = kzalloc(bufsz, GFP_KERNEL);
938 if (!buf) {
9406f797 939 IL_ERR("Can not allocate Buffer\n");
be663ab6
WYG
940 return -ENOMEM;
941 }
942
e7392364
SG
943 pos +=
944 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
945 data->auto_corr_ofdm);
946 pos +=
947 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n",
948 data->auto_corr_ofdm_mrc);
949 pos +=
950 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
951 data->auto_corr_ofdm_x1);
952 pos +=
953 scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n",
954 data->auto_corr_ofdm_mrc_x1);
955 pos +=
956 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
957 data->auto_corr_cck);
958 pos +=
959 scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
960 data->auto_corr_cck_mrc);
961 pos +=
962 scnprintf(buf + pos, bufsz - pos,
963 "last_bad_plcp_cnt_ofdm:\t\t %u\n",
964 data->last_bad_plcp_cnt_ofdm);
965 pos +=
966 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
967 data->last_fa_cnt_ofdm);
968 pos +=
969 scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n",
970 data->last_bad_plcp_cnt_cck);
971 pos +=
972 scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
973 data->last_fa_cnt_cck);
974 pos +=
975 scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
976 data->nrg_curr_state);
977 pos +=
978 scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
979 data->nrg_prev_state);
be663ab6
WYG
980 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
981 for (cnt = 0; cnt < 10; cnt++) {
e7392364
SG
982 pos +=
983 scnprintf(buf + pos, bufsz - pos, " %u",
984 data->nrg_value[cnt]);
be663ab6
WYG
985 }
986 pos += scnprintf(buf + pos, bufsz - pos, "\n");
987 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
988 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
e7392364
SG
989 pos +=
990 scnprintf(buf + pos, bufsz - pos, " %u",
991 data->nrg_silence_rssi[cnt]);
be663ab6
WYG
992 }
993 pos += scnprintf(buf + pos, bufsz - pos, "\n");
e7392364
SG
994 pos +=
995 scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
996 data->nrg_silence_ref);
997 pos +=
998 scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
999 data->nrg_energy_idx);
1000 pos +=
1001 scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1002 data->nrg_silence_idx);
1003 pos +=
1004 scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1005 data->nrg_th_cck);
1006 pos +=
1007 scnprintf(buf + pos, bufsz - pos,
1008 "nrg_auto_corr_silence_diff:\t %u\n",
1009 data->nrg_auto_corr_silence_diff);
1010 pos +=
1011 scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1012 data->num_in_cck_no_fa);
1013 pos +=
1014 scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1015 data->nrg_th_ofdm);
be663ab6
WYG
1016
1017 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1018 kfree(buf);
1019 return ret;
1020}
1021
e7392364 1022static ssize_t
1722f8e1
SG
1023il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf,
1024 size_t count, loff_t *ppos)
e7392364 1025{
be663ab6 1026
46bc8d4b 1027 struct il_priv *il = file->private_data;
be663ab6
WYG
1028 int pos = 0;
1029 int cnt = 0;
1030 char *buf;
e2ebc833 1031 int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
be663ab6 1032 ssize_t ret;
e2ebc833 1033 struct il_chain_noise_data *data;
be663ab6 1034
46bc8d4b 1035 data = &il->chain_noise_data;
be663ab6
WYG
1036 buf = kzalloc(bufsz, GFP_KERNEL);
1037 if (!buf) {
9406f797 1038 IL_ERR("Can not allocate Buffer\n");
be663ab6
WYG
1039 return -ENOMEM;
1040 }
1041
e7392364
SG
1042 pos +=
1043 scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1044 data->active_chains);
1045 pos +=
1046 scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1047 data->chain_noise_a);
1048 pos +=
1049 scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1050 data->chain_noise_b);
1051 pos +=
1052 scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1053 data->chain_noise_c);
1054 pos +=
1055 scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1056 data->chain_signal_a);
1057 pos +=
1058 scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1059 data->chain_signal_b);
1060 pos +=
1061 scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1062 data->chain_signal_c);
1063 pos +=
1064 scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1065 data->beacon_count);
be663ab6
WYG
1066
1067 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1068 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
e7392364
SG
1069 pos +=
1070 scnprintf(buf + pos, bufsz - pos, " %u",
1071 data->disconn_array[cnt]);
be663ab6
WYG
1072 }
1073 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1074 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1075 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
e7392364
SG
1076 pos +=
1077 scnprintf(buf + pos, bufsz - pos, " %u",
1078 data->delta_gain_code[cnt]);
be663ab6
WYG
1079 }
1080 pos += scnprintf(buf + pos, bufsz - pos, "\n");
e7392364
SG
1081 pos +=
1082 scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1083 data->radio_write);
1084 pos +=
1085 scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1086 data->state);
be663ab6
WYG
1087
1088 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1089 kfree(buf);
1090 return ret;
1091}
1092
e7392364 1093static ssize_t
1722f8e1
SG
1094il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf,
1095 size_t count, loff_t *ppos)
be663ab6 1096{
46bc8d4b 1097 struct il_priv *il = file->private_data;
be663ab6
WYG
1098 char buf[60];
1099 int pos = 0;
1100 const size_t bufsz = sizeof(buf);
1101 u32 pwrsave_status;
1102
e7392364
SG
1103 pwrsave_status =
1104 _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK;
be663ab6
WYG
1105
1106 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
e7392364
SG
1107 pos +=
1108 scnprintf(buf + pos, bufsz - pos, "%s\n",
1722f8e1
SG
1109 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1110 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1111 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1112 "error");
be663ab6
WYG
1113
1114 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1115}
1116
e7392364
SG
1117static ssize_t
1118il_dbgfs_clear_ucode_stats_write(struct file *file,
1722f8e1
SG
1119 const char __user *user_buf, size_t count,
1120 loff_t *ppos)
be663ab6 1121{
46bc8d4b 1122 struct il_priv *il = file->private_data;
be663ab6
WYG
1123 char buf[8];
1124 int buf_size;
1125 int clear;
1126
1127 memset(buf, 0, sizeof(buf));
e7392364 1128 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
1129 if (copy_from_user(buf, user_buf, buf_size))
1130 return -EFAULT;
1131 if (sscanf(buf, "%d", &clear) != 1)
1132 return -EFAULT;
1133
ebf0d90d 1134 /* make request to uCode to retrieve stats information */
46bc8d4b 1135 mutex_lock(&il->mutex);
ebf0d90d 1136 il_send_stats_request(il, CMD_SYNC, true);
46bc8d4b 1137 mutex_unlock(&il->mutex);
be663ab6
WYG
1138
1139 return count;
1140}
1141
e7392364 1142static ssize_t
1722f8e1
SG
1143il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf,
1144 size_t count, loff_t *ppos)
e7392364 1145{
be663ab6 1146
46bc8d4b 1147 struct il_priv *il = file->private_data;
be663ab6
WYG
1148 int len = 0;
1149 char buf[20];
1150
c8b03958 1151 len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags));
be663ab6
WYG
1152 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1153}
1154
e7392364 1155static ssize_t
1722f8e1
SG
1156il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf,
1157 size_t count, loff_t *ppos)
e7392364 1158{
be663ab6 1159
46bc8d4b 1160 struct il_priv *il = file->private_data;
be663ab6
WYG
1161 int len = 0;
1162 char buf[20];
1163
e7392364 1164 len =
c8b03958 1165 sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
be663ab6
WYG
1166 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1167}
1168
e7392364 1169static ssize_t
1722f8e1
SG
1170il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count,
1171 loff_t *ppos)
be663ab6 1172{
46bc8d4b 1173 struct il_priv *il = file->private_data;
be663ab6
WYG
1174 char *buf;
1175 int pos = 0;
1176 ssize_t ret = -EFAULT;
1177
c39ae9fd
SG
1178 if (il->ops->lib->dump_fh) {
1179 ret = pos = il->ops->lib->dump_fh(il, &buf, true);
be663ab6 1180 if (buf) {
e7392364
SG
1181 ret =
1182 simple_read_from_buffer(user_buf, count, ppos, buf,
1183 pos);
be663ab6
WYG
1184 kfree(buf);
1185 }
1186 }
1187
1188 return ret;
1189}
1190
e7392364 1191static ssize_t
1722f8e1
SG
1192il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf,
1193 size_t count, loff_t *ppos)
e7392364 1194{
be663ab6 1195
46bc8d4b 1196 struct il_priv *il = file->private_data;
be663ab6
WYG
1197 int pos = 0;
1198 char buf[12];
1199 const size_t bufsz = sizeof(buf);
1200
e7392364
SG
1201 pos +=
1202 scnprintf(buf + pos, bufsz - pos, "%d\n",
1203 il->missed_beacon_threshold);
be663ab6
WYG
1204
1205 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1206}
1207
e7392364 1208static ssize_t
1722f8e1
SG
1209il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf,
1210 size_t count, loff_t *ppos)
be663ab6 1211{
46bc8d4b 1212 struct il_priv *il = file->private_data;
be663ab6
WYG
1213 char buf[8];
1214 int buf_size;
1215 int missed;
1216
1217 memset(buf, 0, sizeof(buf));
e7392364 1218 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
1219 if (copy_from_user(buf, user_buf, buf_size))
1220 return -EFAULT;
1221 if (sscanf(buf, "%d", &missed) != 1)
1222 return -EINVAL;
1223
e2ebc833
SG
1224 if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
1225 missed > IL_MISSED_BEACON_THRESHOLD_MAX)
e7392364 1226 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
be663ab6 1227 else
46bc8d4b 1228 il->missed_beacon_threshold = missed;
be663ab6
WYG
1229
1230 return count;
1231}
1232
e7392364 1233static ssize_t
1722f8e1
SG
1234il_dbgfs_force_reset_read(struct file *file, char __user *user_buf,
1235 size_t count, loff_t *ppos)
e7392364 1236{
be663ab6 1237
46bc8d4b 1238 struct il_priv *il = file->private_data;
dd6d2a8a 1239 int pos = 0;
be663ab6
WYG
1240 char buf[300];
1241 const size_t bufsz = sizeof(buf);
e2ebc833 1242 struct il_force_reset *force_reset;
be663ab6 1243
46bc8d4b 1244 force_reset = &il->force_reset;
dd6d2a8a 1245
e7392364
SG
1246 pos +=
1247 scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n",
1248 force_reset->reset_request_count);
1249 pos +=
1250 scnprintf(buf + pos, bufsz - pos,
1251 "\tnumber of reset request success: %d\n",
1252 force_reset->reset_success_count);
1253 pos +=
1254 scnprintf(buf + pos, bufsz - pos,
1255 "\tnumber of reset request reject: %d\n",
1256 force_reset->reset_reject_count);
1257 pos +=
1258 scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n",
1259 force_reset->reset_duration);
dd6d2a8a 1260
be663ab6
WYG
1261 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1262}
1263
e7392364 1264static ssize_t
1722f8e1
SG
1265il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf,
1266 size_t count, loff_t *ppos)
e7392364 1267{
be663ab6 1268
dd6d2a8a 1269 int ret;
46bc8d4b 1270 struct il_priv *il = file->private_data;
be663ab6 1271
46bc8d4b 1272 ret = il_force_reset(il, true);
dd6d2a8a 1273
be663ab6
WYG
1274 return ret ? ret : count;
1275}
1276
e7392364 1277static ssize_t
1722f8e1
SG
1278il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf,
1279 size_t count, loff_t *ppos)
e7392364 1280{
be663ab6 1281
46bc8d4b 1282 struct il_priv *il = file->private_data;
be663ab6
WYG
1283 char buf[8];
1284 int buf_size;
1285 int timeout;
1286
1287 memset(buf, 0, sizeof(buf));
e7392364 1288 buf_size = min(count, sizeof(buf) - 1);
be663ab6
WYG
1289 if (copy_from_user(buf, user_buf, buf_size))
1290 return -EFAULT;
1291 if (sscanf(buf, "%d", &timeout) != 1)
1292 return -EINVAL;
e2ebc833
SG
1293 if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
1294 timeout = IL_DEF_WD_TIMEOUT;
be663ab6 1295
89ef1ed2 1296 il->cfg->wd_timeout = timeout;
46bc8d4b 1297 il_setup_watchdog(il);
be663ab6
WYG
1298 return count;
1299}
1300
ebf0d90d
SG
1301DEBUGFS_READ_FILE_OPS(rx_stats);
1302DEBUGFS_READ_FILE_OPS(tx_stats);
be663ab6
WYG
1303DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1304DEBUGFS_READ_FILE_OPS(rx_queue);
1305DEBUGFS_READ_FILE_OPS(tx_queue);
1306DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1307DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1308DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1309DEBUGFS_READ_FILE_OPS(sensitivity);
1310DEBUGFS_READ_FILE_OPS(chain_noise);
1311DEBUGFS_READ_FILE_OPS(power_save_status);
ebf0d90d
SG
1312DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats);
1313DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats);
be663ab6
WYG
1314DEBUGFS_READ_FILE_OPS(fh_reg);
1315DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
be663ab6
WYG
1316DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1317DEBUGFS_READ_FILE_OPS(rxon_flags);
1318DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1319DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1320
1321/*
1322 * Create the debugfs files and directories
1323 *
1324 */
e7392364
SG
1325int
1326il_dbgfs_register(struct il_priv *il, const char *name)
be663ab6 1327{
46bc8d4b 1328 struct dentry *phyd = il->hw->wiphy->debugfsdir;
be663ab6
WYG
1329 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1330
1331 dir_drv = debugfs_create_dir(name, phyd);
1332 if (!dir_drv)
1333 return -ENOMEM;
1334
46bc8d4b 1335 il->debugfs_dir = dir_drv;
be663ab6
WYG
1336
1337 dir_data = debugfs_create_dir("data", dir_drv);
1338 if (!dir_data)
1339 goto err;
1340 dir_rf = debugfs_create_dir("rf", dir_drv);
1341 if (!dir_rf)
1342 goto err;
1343 dir_debug = debugfs_create_dir("debug", dir_drv);
1344 if (!dir_debug)
1345 goto err;
1346
1347 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
1348 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
be663ab6
WYG
1349 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
1350 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
1351 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1352 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1353 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1354 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
ebf0d90d
SG
1355 DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR);
1356 DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR);
be663ab6
WYG
1357 DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
1358 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
1359 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
1360 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
ebf0d90d
SG
1361 DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR);
1362 DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR);
be663ab6
WYG
1363 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
1364 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
be663ab6
WYG
1365 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
1366 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
1367 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
1368 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
1369
89ef1ed2 1370 if (il->cfg->sensitivity_calib_by_driver)
be663ab6 1371 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
89ef1ed2 1372 if (il->cfg->chain_noise_calib_by_driver)
be663ab6 1373 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
be663ab6
WYG
1374 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
1375 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
1376 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
89ef1ed2 1377 if (il->cfg->sensitivity_calib_by_driver)
be663ab6 1378 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
46bc8d4b 1379 &il->disable_sens_cal);
89ef1ed2 1380 if (il->cfg->chain_noise_calib_by_driver)
be663ab6 1381 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
46bc8d4b 1382 &il->disable_chain_noise_cal);
e7392364 1383 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal);
be663ab6
WYG
1384 return 0;
1385
1386err:
9406f797 1387 IL_ERR("Can't create the debugfs directory\n");
46bc8d4b 1388 il_dbgfs_unregister(il);
be663ab6
WYG
1389 return -ENOMEM;
1390}
e2ebc833 1391EXPORT_SYMBOL(il_dbgfs_register);
be663ab6
WYG
1392
1393/**
1394 * Remove the debugfs files and directories
1395 *
1396 */
e7392364
SG
1397void
1398il_dbgfs_unregister(struct il_priv *il)
be663ab6 1399{
46bc8d4b 1400 if (!il->debugfs_dir)
be663ab6
WYG
1401 return;
1402
46bc8d4b
SG
1403 debugfs_remove_recursive(il->debugfs_dir);
1404 il->debugfs_dir = NULL;
be663ab6 1405}
e2ebc833 1406EXPORT_SYMBOL(il_dbgfs_unregister);