iwlegacy: rename iwlegacy to il
[deliverable/linux.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
e2ebc833 105static ssize_t il_dbgfs_tx_statistics_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
e2ebc833 145il_dbgfs_clear_traffic_statistics_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
e2ebc833 165static ssize_t il_dbgfs_rx_statistics_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) {
46bc8d4b 361 IL_ERR(il, "NVM size is not multiple of 16.\n");
be663ab6
WYG
362 return -ENODATA;
363 }
364
46bc8d4b 365 ptr = il->eeprom;
be663ab6 366 if (!ptr) {
46bc8d4b 367 IL_ERR(il, "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) {
46bc8d4b 374 IL_ERR(il, "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
46bc8d4b 405 if (!test_bit(STATUS_GEO_CONFIGURED, &il->status))
be663ab6
WYG
406 return -EAGAIN;
407
408 buf = kzalloc(bufsz, GFP_KERNEL);
409 if (!buf) {
46bc8d4b 410 IL_ERR(il, "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
474 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
46bc8d4b 475 test_bit(STATUS_HCMD_ACTIVE, &il->status));
be663ab6 476 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
46bc8d4b 477 test_bit(STATUS_INT_ENABLED, &il->status));
be663ab6 478 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
46bc8d4b 479 test_bit(STATUS_RF_KILL_HW, &il->status));
be663ab6 480 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
46bc8d4b 481 test_bit(STATUS_CT_KILL, &il->status));
be663ab6 482 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
46bc8d4b 483 test_bit(STATUS_INIT, &il->status));
be663ab6 484 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
46bc8d4b 485 test_bit(STATUS_ALIVE, &il->status));
be663ab6 486 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
46bc8d4b 487 test_bit(STATUS_READY, &il->status));
be663ab6 488 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
46bc8d4b 489 test_bit(STATUS_TEMPERATURE, &il->status));
be663ab6 490 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
46bc8d4b 491 test_bit(STATUS_GEO_CONFIGURED, &il->status));
be663ab6 492 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
46bc8d4b 493 test_bit(STATUS_EXIT_PENDING, &il->status));
be663ab6 494 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
46bc8d4b 495 test_bit(STATUS_STATISTICS, &il->status));
be663ab6 496 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
46bc8d4b 497 test_bit(STATUS_SCANNING, &il->status));
be663ab6 498 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
46bc8d4b 499 test_bit(STATUS_SCAN_ABORTING, &il->status));
be663ab6 500 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
46bc8d4b 501 test_bit(STATUS_SCAN_HW, &il->status));
be663ab6 502 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
46bc8d4b 503 test_bit(STATUS_POWER_PMI, &il->status));
be663ab6 504 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
46bc8d4b 505 test_bit(STATUS_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) {
46bc8d4b 522 IL_ERR(il, "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
WYG
537 }
538#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
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;
e2ebc833 602 struct il_rxon_context *ctx;
be663ab6 603 int pos = 0, i;
e2ebc833 604 char buf[256 * NUM_IL_RXON_CTX];
be663ab6
WYG
605 const size_t bufsz = sizeof(buf);
606
46bc8d4b 607 for_each_context(il, ctx) {
be663ab6
WYG
608 pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
609 ctx->ctxid);
610 for (i = 0; i < AC_NUM; i++) {
611 pos += scnprintf(buf + pos, bufsz - pos,
612 "\tcw_min\tcw_max\taifsn\ttxop\n");
613 pos += scnprintf(buf + pos, bufsz - pos,
614 "AC[%d]\t%u\t%u\t%u\t%u\n", i,
615 ctx->qos_data.def_qos_parm.ac[i].cw_min,
616 ctx->qos_data.def_qos_parm.ac[i].cw_max,
617 ctx->qos_data.def_qos_parm.ac[i].aifsn,
618 ctx->qos_data.def_qos_parm.ac[i].edca_txop);
619 }
620 pos += scnprintf(buf + pos, bufsz - pos, "\n");
621 }
622 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
623}
624
e2ebc833 625static ssize_t il_dbgfs_disable_ht40_write(struct file *file,
be663ab6
WYG
626 const char __user *user_buf,
627 size_t count, loff_t *ppos)
628{
46bc8d4b 629 struct il_priv *il = file->private_data;
be663ab6
WYG
630 char buf[8];
631 int buf_size;
632 int ht40;
633
634 memset(buf, 0, sizeof(buf));
635 buf_size = min(count, sizeof(buf) - 1);
636 if (copy_from_user(buf, user_buf, buf_size))
637 return -EFAULT;
638 if (sscanf(buf, "%d", &ht40) != 1)
639 return -EFAULT;
46bc8d4b
SG
640 if (!il_is_any_associated(il))
641 il->disable_ht40 = ht40 ? true : false;
be663ab6 642 else {
46bc8d4b 643 IL_ERR(il, "Sta associated with AP - "
be663ab6
WYG
644 "Change to 40MHz channel support is not allowed\n");
645 return -EINVAL;
646 }
647
648 return count;
649}
650
e2ebc833 651static ssize_t il_dbgfs_disable_ht40_read(struct file *file,
be663ab6
WYG
652 char __user *user_buf,
653 size_t count, loff_t *ppos)
654{
46bc8d4b 655 struct il_priv *il = file->private_data;
be663ab6
WYG
656 char buf[100];
657 int pos = 0;
658 const size_t bufsz = sizeof(buf);
659
660 pos += scnprintf(buf + pos, bufsz - pos,
661 "11n 40MHz Mode: %s\n",
46bc8d4b 662 il->disable_ht40 ? "Disabled" : "Enabled");
be663ab6
WYG
663 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
664}
665
666DEBUGFS_READ_WRITE_FILE_OPS(sram);
be663ab6
WYG
667DEBUGFS_READ_FILE_OPS(nvm);
668DEBUGFS_READ_FILE_OPS(stations);
669DEBUGFS_READ_FILE_OPS(channels);
670DEBUGFS_READ_FILE_OPS(status);
671DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
672DEBUGFS_READ_FILE_OPS(qos);
673DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
674
e2ebc833 675static ssize_t il_dbgfs_traffic_log_read(struct file *file,
be663ab6
WYG
676 char __user *user_buf,
677 size_t count, loff_t *ppos)
678{
46bc8d4b 679 struct il_priv *il = file->private_data;
be663ab6
WYG
680 int pos = 0, ofs = 0;
681 int cnt = 0, entry;
e2ebc833
SG
682 struct il_tx_queue *txq;
683 struct il_queue *q;
46bc8d4b 684 struct il_rx_queue *rxq = &il->rxq;
be663ab6 685 char *buf;
e2ebc833 686 int bufsz = ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
46bc8d4b 687 (il->cfg->base_params->num_of_queues * 32 * 8) + 400;
be663ab6
WYG
688 const u8 *ptr;
689 ssize_t ret;
690
46bc8d4b
SG
691 if (!il->txq) {
692 IL_ERR(il, "txq not ready\n");
be663ab6
WYG
693 return -EAGAIN;
694 }
695 buf = kzalloc(bufsz, GFP_KERNEL);
696 if (!buf) {
46bc8d4b 697 IL_ERR(il, "Can not allocate buffer\n");
be663ab6
WYG
698 return -ENOMEM;
699 }
700 pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
46bc8d4b
SG
701 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
702 txq = &il->txq[cnt];
be663ab6
WYG
703 q = &txq->q;
704 pos += scnprintf(buf + pos, bufsz - pos,
705 "q[%d]: read_ptr: %u, write_ptr: %u\n",
706 cnt, q->read_ptr, q->write_ptr);
707 }
d2ddf621 708 if (il->tx_traffic && (il_debug_level & IL_DL_TX)) {
46bc8d4b 709 ptr = il->tx_traffic;
be663ab6 710 pos += scnprintf(buf + pos, bufsz - pos,
46bc8d4b 711 "Tx Traffic idx: %u\n", il->tx_traffic_idx);
e2ebc833
SG
712 for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
713 for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
be663ab6
WYG
714 entry++, ofs += 16) {
715 pos += scnprintf(buf + pos, bufsz - pos,
716 "0x%.4x ", ofs);
717 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
718 buf + pos, bufsz - pos, 0);
719 pos += strlen(buf + pos);
720 if (bufsz - pos > 0)
721 buf[pos++] = '\n';
722 }
723 }
724 }
725
726 pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
727 pos += scnprintf(buf + pos, bufsz - pos,
728 "read: %u, write: %u\n",
729 rxq->read, rxq->write);
730
d2ddf621 731 if (il->rx_traffic && (il_debug_level & IL_DL_RX)) {
46bc8d4b 732 ptr = il->rx_traffic;
be663ab6 733 pos += scnprintf(buf + pos, bufsz - pos,
46bc8d4b 734 "Rx Traffic idx: %u\n", il->rx_traffic_idx);
e2ebc833
SG
735 for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) {
736 for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16;
be663ab6
WYG
737 entry++, ofs += 16) {
738 pos += scnprintf(buf + pos, bufsz - pos,
739 "0x%.4x ", ofs);
740 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
741 buf + pos, bufsz - pos, 0);
742 pos += strlen(buf + pos);
743 if (bufsz - pos > 0)
744 buf[pos++] = '\n';
745 }
746 }
747 }
748
749 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
750 kfree(buf);
751 return ret;
752}
753
e2ebc833 754static ssize_t il_dbgfs_traffic_log_write(struct file *file,
be663ab6
WYG
755 const char __user *user_buf,
756 size_t count, loff_t *ppos)
757{
46bc8d4b 758 struct il_priv *il = file->private_data;
be663ab6
WYG
759 char buf[8];
760 int buf_size;
761 int traffic_log;
762
763 memset(buf, 0, sizeof(buf));
764 buf_size = min(count, sizeof(buf) - 1);
765 if (copy_from_user(buf, user_buf, buf_size))
766 return -EFAULT;
767 if (sscanf(buf, "%d", &traffic_log) != 1)
768 return -EFAULT;
769 if (traffic_log == 0)
46bc8d4b 770 il_reset_traffic_log(il);
be663ab6
WYG
771
772 return count;
773}
774
e2ebc833 775static ssize_t il_dbgfs_tx_queue_read(struct file *file,
be663ab6
WYG
776 char __user *user_buf,
777 size_t count, loff_t *ppos) {
778
46bc8d4b 779 struct il_priv *il = file->private_data;
e2ebc833
SG
780 struct il_tx_queue *txq;
781 struct il_queue *q;
be663ab6
WYG
782 char *buf;
783 int pos = 0;
784 int cnt;
785 int ret;
786 const size_t bufsz = sizeof(char) * 64 *
46bc8d4b 787 il->cfg->base_params->num_of_queues;
be663ab6 788
46bc8d4b
SG
789 if (!il->txq) {
790 IL_ERR(il, "txq not ready\n");
be663ab6
WYG
791 return -EAGAIN;
792 }
793 buf = kzalloc(bufsz, GFP_KERNEL);
794 if (!buf)
795 return -ENOMEM;
796
46bc8d4b
SG
797 for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) {
798 txq = &il->txq[cnt];
be663ab6
WYG
799 q = &txq->q;
800 pos += scnprintf(buf + pos, bufsz - pos,
801 "hwq %.2d: read=%u write=%u stop=%d"
802 " swq_id=%#.2x (ac %d/hwq %d)\n",
803 cnt, q->read_ptr, q->write_ptr,
46bc8d4b 804 !!test_bit(cnt, il->queue_stopped),
be663ab6
WYG
805 txq->swq_id, txq->swq_id & 3,
806 (txq->swq_id >> 2) & 0x1f);
807 if (cnt >= 4)
808 continue;
809 /* for the ACs, display the stop count too */
810 pos += scnprintf(buf + pos, bufsz - pos,
811 " stop-count: %d\n",
46bc8d4b 812 atomic_read(&il->queue_stop_count[cnt]));
be663ab6
WYG
813 }
814 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
815 kfree(buf);
816 return ret;
817}
818
e2ebc833 819static ssize_t il_dbgfs_rx_queue_read(struct file *file,
be663ab6
WYG
820 char __user *user_buf,
821 size_t count, loff_t *ppos) {
822
46bc8d4b
SG
823 struct il_priv *il = file->private_data;
824 struct il_rx_queue *rxq = &il->rxq;
be663ab6
WYG
825 char buf[256];
826 int pos = 0;
827 const size_t bufsz = sizeof(buf);
828
829 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
830 rxq->read);
831 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
832 rxq->write);
833 pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
834 rxq->free_count);
835 if (rxq->rb_stts) {
836 pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
837 le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
838 } else {
839 pos += scnprintf(buf + pos, bufsz - pos,
840 "closed_rb_num: Not Allocated\n");
841 }
842 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
843}
844
e2ebc833 845static ssize_t il_dbgfs_ucode_rx_stats_read(struct file *file,
be663ab6
WYG
846 char __user *user_buf,
847 size_t count, loff_t *ppos)
848{
46bc8d4b
SG
849 struct il_priv *il = file->private_data;
850 return il->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
be663ab6
WYG
851 user_buf, count, ppos);
852}
853
e2ebc833 854static ssize_t il_dbgfs_ucode_tx_stats_read(struct file *file,
be663ab6
WYG
855 char __user *user_buf,
856 size_t count, loff_t *ppos)
857{
46bc8d4b
SG
858 struct il_priv *il = file->private_data;
859 return il->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
be663ab6
WYG
860 user_buf, count, ppos);
861}
862
e2ebc833 863static ssize_t il_dbgfs_ucode_general_stats_read(struct file *file,
be663ab6
WYG
864 char __user *user_buf,
865 size_t count, loff_t *ppos)
866{
46bc8d4b
SG
867 struct il_priv *il = file->private_data;
868 return il->cfg->ops->lib->debugfs_ops.general_stats_read(file,
be663ab6
WYG
869 user_buf, count, ppos);
870}
871
e2ebc833 872static ssize_t il_dbgfs_sensitivity_read(struct file *file,
be663ab6
WYG
873 char __user *user_buf,
874 size_t count, loff_t *ppos) {
875
46bc8d4b 876 struct il_priv *il = file->private_data;
be663ab6
WYG
877 int pos = 0;
878 int cnt = 0;
879 char *buf;
e2ebc833 880 int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100;
be663ab6 881 ssize_t ret;
e2ebc833 882 struct il_sensitivity_data *data;
be663ab6 883
46bc8d4b 884 data = &il->sensitivity_data;
be663ab6
WYG
885 buf = kzalloc(bufsz, GFP_KERNEL);
886 if (!buf) {
46bc8d4b 887 IL_ERR(il, "Can not allocate Buffer\n");
be663ab6
WYG
888 return -ENOMEM;
889 }
890
891 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
892 data->auto_corr_ofdm);
893 pos += scnprintf(buf + pos, bufsz - pos,
894 "auto_corr_ofdm_mrc:\t\t %u\n",
895 data->auto_corr_ofdm_mrc);
896 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
897 data->auto_corr_ofdm_x1);
898 pos += scnprintf(buf + pos, bufsz - pos,
899 "auto_corr_ofdm_mrc_x1:\t\t %u\n",
900 data->auto_corr_ofdm_mrc_x1);
901 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
902 data->auto_corr_cck);
903 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
904 data->auto_corr_cck_mrc);
905 pos += scnprintf(buf + pos, bufsz - pos,
906 "last_bad_plcp_cnt_ofdm:\t\t %u\n",
907 data->last_bad_plcp_cnt_ofdm);
908 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
909 data->last_fa_cnt_ofdm);
910 pos += scnprintf(buf + pos, bufsz - pos,
911 "last_bad_plcp_cnt_cck:\t\t %u\n",
912 data->last_bad_plcp_cnt_cck);
913 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
914 data->last_fa_cnt_cck);
915 pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
916 data->nrg_curr_state);
917 pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
918 data->nrg_prev_state);
919 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
920 for (cnt = 0; cnt < 10; cnt++) {
921 pos += scnprintf(buf + pos, bufsz - pos, " %u",
922 data->nrg_value[cnt]);
923 }
924 pos += scnprintf(buf + pos, bufsz - pos, "\n");
925 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
926 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
927 pos += scnprintf(buf + pos, bufsz - pos, " %u",
928 data->nrg_silence_rssi[cnt]);
929 }
930 pos += scnprintf(buf + pos, bufsz - pos, "\n");
931 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
932 data->nrg_silence_ref);
933 pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
934 data->nrg_energy_idx);
935 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
936 data->nrg_silence_idx);
937 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
938 data->nrg_th_cck);
939 pos += scnprintf(buf + pos, bufsz - pos,
940 "nrg_auto_corr_silence_diff:\t %u\n",
941 data->nrg_auto_corr_silence_diff);
942 pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
943 data->num_in_cck_no_fa);
944 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
945 data->nrg_th_ofdm);
946
947 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
948 kfree(buf);
949 return ret;
950}
951
952
e2ebc833 953static ssize_t il_dbgfs_chain_noise_read(struct file *file,
be663ab6
WYG
954 char __user *user_buf,
955 size_t count, loff_t *ppos) {
956
46bc8d4b 957 struct il_priv *il = file->private_data;
be663ab6
WYG
958 int pos = 0;
959 int cnt = 0;
960 char *buf;
e2ebc833 961 int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100;
be663ab6 962 ssize_t ret;
e2ebc833 963 struct il_chain_noise_data *data;
be663ab6 964
46bc8d4b 965 data = &il->chain_noise_data;
be663ab6
WYG
966 buf = kzalloc(bufsz, GFP_KERNEL);
967 if (!buf) {
46bc8d4b 968 IL_ERR(il, "Can not allocate Buffer\n");
be663ab6
WYG
969 return -ENOMEM;
970 }
971
972 pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
973 data->active_chains);
974 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
975 data->chain_noise_a);
976 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
977 data->chain_noise_b);
978 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
979 data->chain_noise_c);
980 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
981 data->chain_signal_a);
982 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
983 data->chain_signal_b);
984 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
985 data->chain_signal_c);
986 pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
987 data->beacon_count);
988
989 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
990 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
991 pos += scnprintf(buf + pos, bufsz - pos, " %u",
992 data->disconn_array[cnt]);
993 }
994 pos += scnprintf(buf + pos, bufsz - pos, "\n");
995 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
996 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
997 pos += scnprintf(buf + pos, bufsz - pos, " %u",
998 data->delta_gain_code[cnt]);
999 }
1000 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1001 pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1002 data->radio_write);
1003 pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1004 data->state);
1005
1006 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1007 kfree(buf);
1008 return ret;
1009}
1010
e2ebc833 1011static ssize_t il_dbgfs_power_save_status_read(struct file *file,
be663ab6
WYG
1012 char __user *user_buf,
1013 size_t count, loff_t *ppos)
1014{
46bc8d4b 1015 struct il_priv *il = file->private_data;
be663ab6
WYG
1016 char buf[60];
1017 int pos = 0;
1018 const size_t bufsz = sizeof(buf);
1019 u32 pwrsave_status;
1020
46bc8d4b 1021 pwrsave_status = il_read32(il, CSR_GP_CNTRL) &
be663ab6
WYG
1022 CSR_GP_REG_POWER_SAVE_STATUS_MSK;
1023
1024 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
1025 pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
1026 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1027 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1028 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1029 "error");
1030
1031 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1032}
1033
e2ebc833 1034static ssize_t il_dbgfs_clear_ucode_statistics_write(struct file *file,
be663ab6
WYG
1035 const char __user *user_buf,
1036 size_t count, loff_t *ppos)
1037{
46bc8d4b 1038 struct il_priv *il = file->private_data;
be663ab6
WYG
1039 char buf[8];
1040 int buf_size;
1041 int clear;
1042
1043 memset(buf, 0, sizeof(buf));
1044 buf_size = min(count, sizeof(buf) - 1);
1045 if (copy_from_user(buf, user_buf, buf_size))
1046 return -EFAULT;
1047 if (sscanf(buf, "%d", &clear) != 1)
1048 return -EFAULT;
1049
1050 /* make request to uCode to retrieve statistics information */
46bc8d4b
SG
1051 mutex_lock(&il->mutex);
1052 il_send_statistics_request(il, CMD_SYNC, true);
1053 mutex_unlock(&il->mutex);
be663ab6
WYG
1054
1055 return count;
1056}
1057
e2ebc833 1058static ssize_t il_dbgfs_rxon_flags_read(struct file *file,
be663ab6
WYG
1059 char __user *user_buf,
1060 size_t count, loff_t *ppos) {
1061
46bc8d4b 1062 struct il_priv *il = file->private_data;
be663ab6
WYG
1063 int len = 0;
1064 char buf[20];
1065
1066 len = sprintf(buf, "0x%04X\n",
46bc8d4b 1067 le32_to_cpu(il->contexts[IL_RXON_CTX_BSS].active.flags));
be663ab6
WYG
1068 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1069}
1070
e2ebc833 1071static ssize_t il_dbgfs_rxon_filter_flags_read(struct file *file,
be663ab6
WYG
1072 char __user *user_buf,
1073 size_t count, loff_t *ppos) {
1074
46bc8d4b 1075 struct il_priv *il = file->private_data;
be663ab6
WYG
1076 int len = 0;
1077 char buf[20];
1078
1079 len = sprintf(buf, "0x%04X\n",
46bc8d4b 1080 le32_to_cpu(il->contexts[IL_RXON_CTX_BSS].active.filter_flags));
be663ab6
WYG
1081 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1082}
1083
e2ebc833 1084static ssize_t il_dbgfs_fh_reg_read(struct file *file,
be663ab6
WYG
1085 char __user *user_buf,
1086 size_t count, loff_t *ppos)
1087{
46bc8d4b 1088 struct il_priv *il = file->private_data;
be663ab6
WYG
1089 char *buf;
1090 int pos = 0;
1091 ssize_t ret = -EFAULT;
1092
46bc8d4b
SG
1093 if (il->cfg->ops->lib->dump_fh) {
1094 ret = pos = il->cfg->ops->lib->dump_fh(il, &buf, true);
be663ab6
WYG
1095 if (buf) {
1096 ret = simple_read_from_buffer(user_buf,
1097 count, ppos, buf, pos);
1098 kfree(buf);
1099 }
1100 }
1101
1102 return ret;
1103}
1104
e2ebc833 1105static ssize_t il_dbgfs_missed_beacon_read(struct file *file,
be663ab6
WYG
1106 char __user *user_buf,
1107 size_t count, loff_t *ppos) {
1108
46bc8d4b 1109 struct il_priv *il = file->private_data;
be663ab6
WYG
1110 int pos = 0;
1111 char buf[12];
1112 const size_t bufsz = sizeof(buf);
1113
1114 pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
46bc8d4b 1115 il->missed_beacon_threshold);
be663ab6
WYG
1116
1117 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1118}
1119
e2ebc833 1120static ssize_t il_dbgfs_missed_beacon_write(struct file *file,
be663ab6
WYG
1121 const char __user *user_buf,
1122 size_t count, loff_t *ppos)
1123{
46bc8d4b 1124 struct il_priv *il = file->private_data;
be663ab6
WYG
1125 char buf[8];
1126 int buf_size;
1127 int missed;
1128
1129 memset(buf, 0, sizeof(buf));
1130 buf_size = min(count, sizeof(buf) - 1);
1131 if (copy_from_user(buf, user_buf, buf_size))
1132 return -EFAULT;
1133 if (sscanf(buf, "%d", &missed) != 1)
1134 return -EINVAL;
1135
e2ebc833
SG
1136 if (missed < IL_MISSED_BEACON_THRESHOLD_MIN ||
1137 missed > IL_MISSED_BEACON_THRESHOLD_MAX)
46bc8d4b 1138 il->missed_beacon_threshold =
e2ebc833 1139 IL_MISSED_BEACON_THRESHOLD_DEF;
be663ab6 1140 else
46bc8d4b 1141 il->missed_beacon_threshold = missed;
be663ab6
WYG
1142
1143 return count;
1144}
1145
e2ebc833 1146static ssize_t il_dbgfs_force_reset_read(struct file *file,
be663ab6
WYG
1147 char __user *user_buf,
1148 size_t count, loff_t *ppos) {
1149
46bc8d4b 1150 struct il_priv *il = file->private_data;
dd6d2a8a 1151 int pos = 0;
be663ab6
WYG
1152 char buf[300];
1153 const size_t bufsz = sizeof(buf);
e2ebc833 1154 struct il_force_reset *force_reset;
be663ab6 1155
46bc8d4b 1156 force_reset = &il->force_reset;
dd6d2a8a
SG
1157
1158 pos += scnprintf(buf + pos, bufsz - pos,
1159 "\tnumber of reset request: %d\n",
1160 force_reset->reset_request_count);
1161 pos += scnprintf(buf + pos, bufsz - pos,
1162 "\tnumber of reset request success: %d\n",
1163 force_reset->reset_success_count);
1164 pos += scnprintf(buf + pos, bufsz - pos,
1165 "\tnumber of reset request reject: %d\n",
1166 force_reset->reset_reject_count);
1167 pos += scnprintf(buf + pos, bufsz - pos,
1168 "\treset duration: %lu\n",
1169 force_reset->reset_duration);
1170
be663ab6
WYG
1171 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1172}
1173
e2ebc833 1174static ssize_t il_dbgfs_force_reset_write(struct file *file,
be663ab6
WYG
1175 const char __user *user_buf,
1176 size_t count, loff_t *ppos) {
1177
dd6d2a8a 1178 int ret;
46bc8d4b 1179 struct il_priv *il = file->private_data;
be663ab6 1180
46bc8d4b 1181 ret = il_force_reset(il, true);
dd6d2a8a 1182
be663ab6
WYG
1183 return ret ? ret : count;
1184}
1185
e2ebc833 1186static ssize_t il_dbgfs_wd_timeout_write(struct file *file,
be663ab6
WYG
1187 const char __user *user_buf,
1188 size_t count, loff_t *ppos) {
1189
46bc8d4b 1190 struct il_priv *il = file->private_data;
be663ab6
WYG
1191 char buf[8];
1192 int buf_size;
1193 int timeout;
1194
1195 memset(buf, 0, sizeof(buf));
1196 buf_size = min(count, sizeof(buf) - 1);
1197 if (copy_from_user(buf, user_buf, buf_size))
1198 return -EFAULT;
1199 if (sscanf(buf, "%d", &timeout) != 1)
1200 return -EINVAL;
e2ebc833
SG
1201 if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT)
1202 timeout = IL_DEF_WD_TIMEOUT;
be663ab6 1203
46bc8d4b
SG
1204 il->cfg->base_params->wd_timeout = timeout;
1205 il_setup_watchdog(il);
be663ab6
WYG
1206 return count;
1207}
1208
1209DEBUGFS_READ_FILE_OPS(rx_statistics);
1210DEBUGFS_READ_FILE_OPS(tx_statistics);
1211DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1212DEBUGFS_READ_FILE_OPS(rx_queue);
1213DEBUGFS_READ_FILE_OPS(tx_queue);
1214DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1215DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1216DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1217DEBUGFS_READ_FILE_OPS(sensitivity);
1218DEBUGFS_READ_FILE_OPS(chain_noise);
1219DEBUGFS_READ_FILE_OPS(power_save_status);
1220DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
1221DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
be663ab6
WYG
1222DEBUGFS_READ_FILE_OPS(fh_reg);
1223DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
be663ab6
WYG
1224DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1225DEBUGFS_READ_FILE_OPS(rxon_flags);
1226DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1227DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1228
1229/*
1230 * Create the debugfs files and directories
1231 *
1232 */
46bc8d4b 1233int il_dbgfs_register(struct il_priv *il, const char *name)
be663ab6 1234{
46bc8d4b 1235 struct dentry *phyd = il->hw->wiphy->debugfsdir;
be663ab6
WYG
1236 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1237
1238 dir_drv = debugfs_create_dir(name, phyd);
1239 if (!dir_drv)
1240 return -ENOMEM;
1241
46bc8d4b 1242 il->debugfs_dir = dir_drv;
be663ab6
WYG
1243
1244 dir_data = debugfs_create_dir("data", dir_drv);
1245 if (!dir_data)
1246 goto err;
1247 dir_rf = debugfs_create_dir("rf", dir_drv);
1248 if (!dir_rf)
1249 goto err;
1250 dir_debug = debugfs_create_dir("debug", dir_drv);
1251 if (!dir_debug)
1252 goto err;
1253
1254 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
1255 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
be663ab6
WYG
1256 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
1257 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
1258 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1259 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1260 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1261 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
1262 DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
1263 DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
1264 DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
1265 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
1266 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
1267 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
1268 DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
1269 DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
1270 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
1271 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
be663ab6
WYG
1272 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
1273 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
1274 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
1275 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
1276
46bc8d4b 1277 if (il->cfg->base_params->sensitivity_calib_by_driver)
be663ab6 1278 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
46bc8d4b 1279 if (il->cfg->base_params->chain_noise_calib_by_driver)
be663ab6 1280 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
be663ab6
WYG
1281 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
1282 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
1283 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
46bc8d4b 1284 if (il->cfg->base_params->sensitivity_calib_by_driver)
be663ab6 1285 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
46bc8d4b
SG
1286 &il->disable_sens_cal);
1287 if (il->cfg->base_params->chain_noise_calib_by_driver)
be663ab6 1288 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
46bc8d4b 1289 &il->disable_chain_noise_cal);
be663ab6 1290 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
46bc8d4b 1291 &il->disable_tx_power_cal);
be663ab6
WYG
1292 return 0;
1293
1294err:
46bc8d4b
SG
1295 IL_ERR(il, "Can't create the debugfs directory\n");
1296 il_dbgfs_unregister(il);
be663ab6
WYG
1297 return -ENOMEM;
1298}
e2ebc833 1299EXPORT_SYMBOL(il_dbgfs_register);
be663ab6
WYG
1300
1301/**
1302 * Remove the debugfs files and directories
1303 *
1304 */
46bc8d4b 1305void il_dbgfs_unregister(struct il_priv *il)
be663ab6 1306{
46bc8d4b 1307 if (!il->debugfs_dir)
be663ab6
WYG
1308 return;
1309
46bc8d4b
SG
1310 debugfs_remove_recursive(il->debugfs_dir);
1311 il->debugfs_dir = NULL;
be663ab6 1312}
e2ebc833 1313EXPORT_SYMBOL(il_dbgfs_unregister);
This page took 0.161485 seconds and 5 git commands to generate.