iwlegacy: change some symbols duplicated from iwlwifi directory
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / net / wireless / iwlegacy / iwl-debugfs.c
blob2d32438b4cb8c531f4a73dc9e98c567e83363203
1 /******************************************************************************
3 * GPL LICENSE SUMMARY
5 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
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.
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.
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
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
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>
32 #include "iwl-dev.h"
33 #include "iwl-debug.h"
34 #include "iwl-core.h"
35 #include "iwl-io.h"
37 /* create and remove of files */
38 #define DEBUGFS_ADD_FILE(name, parent, mode) do { \
39 if (!debugfs_create_file(#name, mode, parent, priv, \
40 &iwl_legacy_dbgfs_##name##_ops)) \
41 goto err; \
42 } while (0)
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)
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)
60 /* file operation */
61 #define DEBUGFS_READ_FUNC(name) \
62 static ssize_t iwl_legacy_dbgfs_##name##_read(struct file *file, \
63 char __user *user_buf, \
64 size_t count, loff_t *ppos);
66 #define DEBUGFS_WRITE_FUNC(name) \
67 static ssize_t iwl_legacy_dbgfs_##name##_write(struct file *file, \
68 const char __user *user_buf, \
69 size_t count, loff_t *ppos);
72 static int
73 iwl_legacy_dbgfs_open_file_generic(struct inode *inode, struct file *file)
75 file->private_data = inode->i_private;
76 return 0;
79 #define DEBUGFS_READ_FILE_OPS(name) \
80 DEBUGFS_READ_FUNC(name); \
81 static const struct file_operations iwl_legacy_dbgfs_##name##_ops = { \
82 .read = iwl_legacy_dbgfs_##name##_read, \
83 .open = iwl_legacy_dbgfs_open_file_generic, \
84 .llseek = generic_file_llseek, \
87 #define DEBUGFS_WRITE_FILE_OPS(name) \
88 DEBUGFS_WRITE_FUNC(name); \
89 static const struct file_operations iwl_legacy_dbgfs_##name##_ops = { \
90 .write = iwl_legacy_dbgfs_##name##_write, \
91 .open = iwl_legacy_dbgfs_open_file_generic, \
92 .llseek = generic_file_llseek, \
95 #define DEBUGFS_READ_WRITE_FILE_OPS(name) \
96 DEBUGFS_READ_FUNC(name); \
97 DEBUGFS_WRITE_FUNC(name); \
98 static const struct file_operations iwl_legacy_dbgfs_##name##_ops = { \
99 .write = iwl_legacy_dbgfs_##name##_write, \
100 .read = iwl_legacy_dbgfs_##name##_read, \
101 .open = iwl_legacy_dbgfs_open_file_generic, \
102 .llseek = generic_file_llseek, \
105 static ssize_t iwl_legacy_dbgfs_tx_statistics_read(struct file *file,
106 char __user *user_buf,
107 size_t count, loff_t *ppos) {
109 struct iwl_priv *priv = file->private_data;
110 char *buf;
111 int pos = 0;
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",
124 iwl_legacy_get_mgmt_string(cnt),
125 priv->tx_stats.mgmt[cnt]);
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",
131 iwl_legacy_get_ctrl_string(cnt),
132 priv->tx_stats.ctrl[cnt]);
134 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
135 pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
136 priv->tx_stats.data_cnt);
137 pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
138 priv->tx_stats.data_bytes);
139 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
140 kfree(buf);
141 return ret;
144 static ssize_t
145 iwl_legacy_dbgfs_clear_traffic_statistics_write(struct file *file,
146 const char __user *user_buf,
147 size_t count, loff_t *ppos)
149 struct iwl_priv *priv = file->private_data;
150 u32 clear_flag;
151 char buf[8];
152 int buf_size;
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;
160 iwl_legacy_clear_traffic_stats(priv);
162 return count;
165 static ssize_t iwl_legacy_dbgfs_rx_statistics_read(struct file *file,
166 char __user *user_buf,
167 size_t count, loff_t *ppos) {
169 struct iwl_priv *priv = file->private_data;
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;
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",
184 iwl_legacy_get_mgmt_string(cnt),
185 priv->rx_stats.mgmt[cnt]);
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",
191 iwl_legacy_get_ctrl_string(cnt),
192 priv->rx_stats.ctrl[cnt]);
194 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
195 pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
196 priv->rx_stats.data_cnt);
197 pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
198 priv->rx_stats.data_bytes);
200 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
201 kfree(buf);
202 return ret;
205 #define BYTE1_MASK 0x000000ff;
206 #define BYTE2_MASK 0x0000ffff;
207 #define BYTE3_MASK 0x00ffffff;
208 static ssize_t iwl_legacy_dbgfs_sram_read(struct file *file,
209 char __user *user_buf,
210 size_t count, loff_t *ppos)
212 u32 val;
213 char *buf;
214 ssize_t ret;
215 int i;
216 int pos = 0;
217 struct iwl_priv *priv = file->private_data;
218 size_t bufsz;
220 /* default is to dump the entire data segment */
221 if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
222 priv->dbgfs_sram_offset = 0x800000;
223 if (priv->ucode_type == UCODE_INIT)
224 priv->dbgfs_sram_len = priv->ucode_init_data.len;
225 else
226 priv->dbgfs_sram_len = priv->ucode_data.len;
228 bufsz = 30 + priv->dbgfs_sram_len * sizeof(char) * 10;
229 buf = kmalloc(bufsz, GFP_KERNEL);
230 if (!buf)
231 return -ENOMEM;
232 pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
233 priv->dbgfs_sram_len);
234 pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
235 priv->dbgfs_sram_offset);
236 for (i = priv->dbgfs_sram_len; i > 0; i -= 4) {
237 val = iwl_legacy_read_targ_mem(priv, priv->dbgfs_sram_offset + \
238 priv->dbgfs_sram_len - i);
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;
252 if (!(i % 16))
253 pos += scnprintf(buf + pos, bufsz - pos, "\n");
254 pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
256 pos += scnprintf(buf + pos, bufsz - pos, "\n");
258 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
259 kfree(buf);
260 return ret;
263 static ssize_t iwl_legacy_dbgfs_sram_write(struct file *file,
264 const char __user *user_buf,
265 size_t count, loff_t *ppos)
267 struct iwl_priv *priv = file->private_data;
268 char buf[64];
269 int buf_size;
270 u32 offset, len;
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;
277 if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
278 priv->dbgfs_sram_offset = offset;
279 priv->dbgfs_sram_len = len;
280 } else {
281 priv->dbgfs_sram_offset = 0;
282 priv->dbgfs_sram_len = 0;
285 return count;
288 static ssize_t
289 iwl_legacy_dbgfs_stations_read(struct file *file, char __user *user_buf,
290 size_t count, loff_t *ppos)
292 struct iwl_priv *priv = file->private_data;
293 struct iwl_station_entry *station;
294 int max_sta = priv->hw_params.max_stations;
295 char *buf;
296 int i, j, pos = 0;
297 ssize_t ret;
298 /* Add 30 for initial string */
299 const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
301 buf = kmalloc(bufsz, GFP_KERNEL);
302 if (!buf)
303 return -ENOMEM;
305 pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
306 priv->num_stations);
308 for (i = 0; i < max_sta; i++) {
309 station = &priv->stations[i];
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");
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);
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");
338 pos += scnprintf(buf + pos, bufsz - pos, "\n");
341 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
342 kfree(buf);
343 return ret;
346 static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
347 char __user *user_buf,
348 size_t count,
349 loff_t *ppos)
351 ssize_t ret;
352 struct iwl_priv *priv = file->private_data;
353 int pos = 0, ofs = 0, buf_size = 0;
354 const u8 *ptr;
355 char *buf;
356 u16 eeprom_ver;
357 size_t eeprom_len = priv->cfg->base_params->eeprom_size;
358 buf_size = 4 * eeprom_len + 256;
360 if (eeprom_len % 16) {
361 IWL_ERR(priv, "NVM size is not multiple of 16.\n");
362 return -ENODATA;
365 ptr = priv->eeprom;
366 if (!ptr) {
367 IWL_ERR(priv, "Invalid EEPROM memory\n");
368 return -ENOMEM;
371 /* 4 characters for byte 0xYY */
372 buf = kzalloc(buf_size, GFP_KERNEL);
373 if (!buf) {
374 IWL_ERR(priv, "Can not allocate Buffer\n");
375 return -ENOMEM;
377 eeprom_ver = iwl_legacy_eeprom_query16(priv, EEPROM_VERSION);
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';
389 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
390 kfree(buf);
391 return ret;
394 static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file,
395 char __user *user_buf,
396 size_t count, loff_t *ppos)
398 struct iwl_priv *priv = file->private_data;
399 char *buf;
400 int pos = 0;
401 ssize_t ret = -ENOMEM;
403 ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
404 priv, true, &buf, true);
405 if (buf) {
406 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
407 kfree(buf);
409 return ret;
412 static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file,
413 const char __user *user_buf,
414 size_t count, loff_t *ppos)
416 struct iwl_priv *priv = file->private_data;
417 u32 event_log_flag;
418 char buf[8];
419 int buf_size;
421 memset(buf, 0, sizeof(buf));
422 buf_size = min(count, sizeof(buf) - 1);
423 if (copy_from_user(buf, user_buf, buf_size))
424 return -EFAULT;
425 if (sscanf(buf, "%d", &event_log_flag) != 1)
426 return -EFAULT;
427 if (event_log_flag == 1)
428 priv->cfg->ops->lib->dump_nic_event_log(priv, true,
429 NULL, false);
431 return count;
436 static ssize_t
437 iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
438 size_t count, loff_t *ppos)
440 struct iwl_priv *priv = file->private_data;
441 struct ieee80211_channel *channels = NULL;
442 const struct ieee80211_supported_band *supp_band = NULL;
443 int pos = 0, i, bufsz = PAGE_SIZE;
444 char *buf;
445 ssize_t ret;
447 if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
448 return -EAGAIN;
450 buf = kzalloc(bufsz, GFP_KERNEL);
451 if (!buf) {
452 IWL_ERR(priv, "Can not allocate Buffer\n");
453 return -ENOMEM;
456 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
457 if (supp_band) {
458 channels = supp_band->channels;
460 pos += scnprintf(buf + pos, bufsz - pos,
461 "Displaying %d channels in 2.4GHz band 802.11bg):\n",
462 supp_band->n_channels);
464 for (i = 0; i < supp_band->n_channels; i++)
465 pos += scnprintf(buf + pos, bufsz - pos,
466 "%d: %ddBm: BSS%s%s, %s.\n",
467 channels[i].hw_value,
468 channels[i].max_power,
469 channels[i].flags & IEEE80211_CHAN_RADAR ?
470 " (IEEE 802.11h required)" : "",
471 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
472 || (channels[i].flags &
473 IEEE80211_CHAN_RADAR)) ? "" :
474 ", IBSS",
475 channels[i].flags &
476 IEEE80211_CHAN_PASSIVE_SCAN ?
477 "passive only" : "active/passive");
479 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
480 if (supp_band) {
481 channels = supp_band->channels;
483 pos += scnprintf(buf + pos, bufsz - pos,
484 "Displaying %d channels in 5.2GHz band (802.11a)\n",
485 supp_band->n_channels);
487 for (i = 0; i < supp_band->n_channels; i++)
488 pos += scnprintf(buf + pos, bufsz - pos,
489 "%d: %ddBm: BSS%s%s, %s.\n",
490 channels[i].hw_value,
491 channels[i].max_power,
492 channels[i].flags & IEEE80211_CHAN_RADAR ?
493 " (IEEE 802.11h required)" : "",
494 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
495 || (channels[i].flags &
496 IEEE80211_CHAN_RADAR)) ? "" :
497 ", IBSS",
498 channels[i].flags &
499 IEEE80211_CHAN_PASSIVE_SCAN ?
500 "passive only" : "active/passive");
502 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
503 kfree(buf);
504 return ret;
507 static ssize_t iwl_legacy_dbgfs_status_read(struct file *file,
508 char __user *user_buf,
509 size_t count, loff_t *ppos) {
511 struct iwl_priv *priv = file->private_data;
512 char buf[512];
513 int pos = 0;
514 const size_t bufsz = sizeof(buf);
516 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
517 test_bit(STATUS_HCMD_ACTIVE, &priv->status));
518 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
519 test_bit(STATUS_INT_ENABLED, &priv->status));
520 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
521 test_bit(STATUS_RF_KILL_HW, &priv->status));
522 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
523 test_bit(STATUS_CT_KILL, &priv->status));
524 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
525 test_bit(STATUS_INIT, &priv->status));
526 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
527 test_bit(STATUS_ALIVE, &priv->status));
528 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
529 test_bit(STATUS_READY, &priv->status));
530 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
531 test_bit(STATUS_TEMPERATURE, &priv->status));
532 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
533 test_bit(STATUS_GEO_CONFIGURED, &priv->status));
534 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
535 test_bit(STATUS_EXIT_PENDING, &priv->status));
536 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
537 test_bit(STATUS_STATISTICS, &priv->status));
538 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
539 test_bit(STATUS_SCANNING, &priv->status));
540 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
541 test_bit(STATUS_SCAN_ABORTING, &priv->status));
542 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
543 test_bit(STATUS_SCAN_HW, &priv->status));
544 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
545 test_bit(STATUS_POWER_PMI, &priv->status));
546 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
547 test_bit(STATUS_FW_ERROR, &priv->status));
548 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
551 static ssize_t iwl_legacy_dbgfs_interrupt_read(struct file *file,
552 char __user *user_buf,
553 size_t count, loff_t *ppos) {
555 struct iwl_priv *priv = file->private_data;
556 int pos = 0;
557 int cnt = 0;
558 char *buf;
559 int bufsz = 24 * 64; /* 24 items * 64 char per item */
560 ssize_t ret;
562 buf = kzalloc(bufsz, GFP_KERNEL);
563 if (!buf) {
564 IWL_ERR(priv, "Can not allocate Buffer\n");
565 return -ENOMEM;
568 pos += scnprintf(buf + pos, bufsz - pos,
569 "Interrupt Statistics Report:\n");
571 pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
572 priv->isr_stats.hw);
573 pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
574 priv->isr_stats.sw);
575 if (priv->isr_stats.sw || priv->isr_stats.hw) {
576 pos += scnprintf(buf + pos, bufsz - pos,
577 "\tLast Restarting Code: 0x%X\n",
578 priv->isr_stats.err_code);
580 #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
581 pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
582 priv->isr_stats.sch);
583 pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
584 priv->isr_stats.alive);
585 #endif
586 pos += scnprintf(buf + pos, bufsz - pos,
587 "HW RF KILL switch toggled:\t %u\n",
588 priv->isr_stats.rfkill);
590 pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
591 priv->isr_stats.ctkill);
593 pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
594 priv->isr_stats.wakeup);
596 pos += scnprintf(buf + pos, bufsz - pos,
597 "Rx command responses:\t\t %u\n",
598 priv->isr_stats.rx);
599 for (cnt = 0; cnt < REPLY_MAX; cnt++) {
600 if (priv->isr_stats.rx_handlers[cnt] > 0)
601 pos += scnprintf(buf + pos, bufsz - pos,
602 "\tRx handler[%36s]:\t\t %u\n",
603 iwl_legacy_get_cmd_string(cnt),
604 priv->isr_stats.rx_handlers[cnt]);
607 pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
608 priv->isr_stats.tx);
610 pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
611 priv->isr_stats.unhandled);
613 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
614 kfree(buf);
615 return ret;
618 static ssize_t iwl_legacy_dbgfs_interrupt_write(struct file *file,
619 const char __user *user_buf,
620 size_t count, loff_t *ppos)
622 struct iwl_priv *priv = file->private_data;
623 char buf[8];
624 int buf_size;
625 u32 reset_flag;
627 memset(buf, 0, sizeof(buf));
628 buf_size = min(count, sizeof(buf) - 1);
629 if (copy_from_user(buf, user_buf, buf_size))
630 return -EFAULT;
631 if (sscanf(buf, "%x", &reset_flag) != 1)
632 return -EFAULT;
633 if (reset_flag == 0)
634 iwl_legacy_clear_isr_stats(priv);
636 return count;
639 static ssize_t
640 iwl_legacy_dbgfs_qos_read(struct file *file, char __user *user_buf,
641 size_t count, loff_t *ppos)
643 struct iwl_priv *priv = file->private_data;
644 struct iwl_rxon_context *ctx;
645 int pos = 0, i;
646 char buf[256 * NUM_IWL_RXON_CTX];
647 const size_t bufsz = sizeof(buf);
649 for_each_context(priv, ctx) {
650 pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
651 ctx->ctxid);
652 for (i = 0; i < AC_NUM; i++) {
653 pos += scnprintf(buf + pos, bufsz - pos,
654 "\tcw_min\tcw_max\taifsn\ttxop\n");
655 pos += scnprintf(buf + pos, bufsz - pos,
656 "AC[%d]\t%u\t%u\t%u\t%u\n", i,
657 ctx->qos_data.def_qos_parm.ac[i].cw_min,
658 ctx->qos_data.def_qos_parm.ac[i].cw_max,
659 ctx->qos_data.def_qos_parm.ac[i].aifsn,
660 ctx->qos_data.def_qos_parm.ac[i].edca_txop);
662 pos += scnprintf(buf + pos, bufsz - pos, "\n");
664 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
667 static ssize_t iwl_legacy_dbgfs_disable_ht40_write(struct file *file,
668 const char __user *user_buf,
669 size_t count, loff_t *ppos)
671 struct iwl_priv *priv = file->private_data;
672 char buf[8];
673 int buf_size;
674 int ht40;
676 memset(buf, 0, sizeof(buf));
677 buf_size = min(count, sizeof(buf) - 1);
678 if (copy_from_user(buf, user_buf, buf_size))
679 return -EFAULT;
680 if (sscanf(buf, "%d", &ht40) != 1)
681 return -EFAULT;
682 if (!iwl_legacy_is_any_associated(priv))
683 priv->disable_ht40 = ht40 ? true : false;
684 else {
685 IWL_ERR(priv, "Sta associated with AP - "
686 "Change to 40MHz channel support is not allowed\n");
687 return -EINVAL;
690 return count;
693 static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
694 char __user *user_buf,
695 size_t count, loff_t *ppos)
697 struct iwl_priv *priv = file->private_data;
698 char buf[100];
699 int pos = 0;
700 const size_t bufsz = sizeof(buf);
702 pos += scnprintf(buf + pos, bufsz - pos,
703 "11n 40MHz Mode: %s\n",
704 priv->disable_ht40 ? "Disabled" : "Enabled");
705 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
708 DEBUGFS_READ_WRITE_FILE_OPS(sram);
709 DEBUGFS_READ_WRITE_FILE_OPS(log_event);
710 DEBUGFS_READ_FILE_OPS(nvm);
711 DEBUGFS_READ_FILE_OPS(stations);
712 DEBUGFS_READ_FILE_OPS(channels);
713 DEBUGFS_READ_FILE_OPS(status);
714 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
715 DEBUGFS_READ_FILE_OPS(qos);
716 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
718 static ssize_t iwl_legacy_dbgfs_traffic_log_read(struct file *file,
719 char __user *user_buf,
720 size_t count, loff_t *ppos)
722 struct iwl_priv *priv = file->private_data;
723 int pos = 0, ofs = 0;
724 int cnt = 0, entry;
725 struct iwl_tx_queue *txq;
726 struct iwl_queue *q;
727 struct iwl_rx_queue *rxq = &priv->rxq;
728 char *buf;
729 int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
730 (priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
731 const u8 *ptr;
732 ssize_t ret;
734 if (!priv->txq) {
735 IWL_ERR(priv, "txq not ready\n");
736 return -EAGAIN;
738 buf = kzalloc(bufsz, GFP_KERNEL);
739 if (!buf) {
740 IWL_ERR(priv, "Can not allocate buffer\n");
741 return -ENOMEM;
743 pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
744 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
745 txq = &priv->txq[cnt];
746 q = &txq->q;
747 pos += scnprintf(buf + pos, bufsz - pos,
748 "q[%d]: read_ptr: %u, write_ptr: %u\n",
749 cnt, q->read_ptr, q->write_ptr);
751 if (priv->tx_traffic && (iwlegacy_debug_level & IWL_DL_TX)) {
752 ptr = priv->tx_traffic;
753 pos += scnprintf(buf + pos, bufsz - pos,
754 "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
755 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
756 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
757 entry++, ofs += 16) {
758 pos += scnprintf(buf + pos, bufsz - pos,
759 "0x%.4x ", ofs);
760 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
761 buf + pos, bufsz - pos, 0);
762 pos += strlen(buf + pos);
763 if (bufsz - pos > 0)
764 buf[pos++] = '\n';
769 pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
770 pos += scnprintf(buf + pos, bufsz - pos,
771 "read: %u, write: %u\n",
772 rxq->read, rxq->write);
774 if (priv->rx_traffic && (iwlegacy_debug_level & IWL_DL_RX)) {
775 ptr = priv->rx_traffic;
776 pos += scnprintf(buf + pos, bufsz - pos,
777 "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
778 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
779 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
780 entry++, ofs += 16) {
781 pos += scnprintf(buf + pos, bufsz - pos,
782 "0x%.4x ", ofs);
783 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
784 buf + pos, bufsz - pos, 0);
785 pos += strlen(buf + pos);
786 if (bufsz - pos > 0)
787 buf[pos++] = '\n';
792 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
793 kfree(buf);
794 return ret;
797 static ssize_t iwl_legacy_dbgfs_traffic_log_write(struct file *file,
798 const char __user *user_buf,
799 size_t count, loff_t *ppos)
801 struct iwl_priv *priv = file->private_data;
802 char buf[8];
803 int buf_size;
804 int traffic_log;
806 memset(buf, 0, sizeof(buf));
807 buf_size = min(count, sizeof(buf) - 1);
808 if (copy_from_user(buf, user_buf, buf_size))
809 return -EFAULT;
810 if (sscanf(buf, "%d", &traffic_log) != 1)
811 return -EFAULT;
812 if (traffic_log == 0)
813 iwl_legacy_reset_traffic_log(priv);
815 return count;
818 static ssize_t iwl_legacy_dbgfs_tx_queue_read(struct file *file,
819 char __user *user_buf,
820 size_t count, loff_t *ppos) {
822 struct iwl_priv *priv = file->private_data;
823 struct iwl_tx_queue *txq;
824 struct iwl_queue *q;
825 char *buf;
826 int pos = 0;
827 int cnt;
828 int ret;
829 const size_t bufsz = sizeof(char) * 64 *
830 priv->cfg->base_params->num_of_queues;
832 if (!priv->txq) {
833 IWL_ERR(priv, "txq not ready\n");
834 return -EAGAIN;
836 buf = kzalloc(bufsz, GFP_KERNEL);
837 if (!buf)
838 return -ENOMEM;
840 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
841 txq = &priv->txq[cnt];
842 q = &txq->q;
843 pos += scnprintf(buf + pos, bufsz - pos,
844 "hwq %.2d: read=%u write=%u stop=%d"
845 " swq_id=%#.2x (ac %d/hwq %d)\n",
846 cnt, q->read_ptr, q->write_ptr,
847 !!test_bit(cnt, priv->queue_stopped),
848 txq->swq_id, txq->swq_id & 3,
849 (txq->swq_id >> 2) & 0x1f);
850 if (cnt >= 4)
851 continue;
852 /* for the ACs, display the stop count too */
853 pos += scnprintf(buf + pos, bufsz - pos,
854 " stop-count: %d\n",
855 atomic_read(&priv->queue_stop_count[cnt]));
857 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
858 kfree(buf);
859 return ret;
862 static ssize_t iwl_legacy_dbgfs_rx_queue_read(struct file *file,
863 char __user *user_buf,
864 size_t count, loff_t *ppos) {
866 struct iwl_priv *priv = file->private_data;
867 struct iwl_rx_queue *rxq = &priv->rxq;
868 char buf[256];
869 int pos = 0;
870 const size_t bufsz = sizeof(buf);
872 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
873 rxq->read);
874 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
875 rxq->write);
876 pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
877 rxq->free_count);
878 if (rxq->rb_stts) {
879 pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
880 le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
881 } else {
882 pos += scnprintf(buf + pos, bufsz - pos,
883 "closed_rb_num: Not Allocated\n");
885 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
888 static ssize_t iwl_legacy_dbgfs_ucode_rx_stats_read(struct file *file,
889 char __user *user_buf,
890 size_t count, loff_t *ppos)
892 struct iwl_priv *priv = file->private_data;
893 return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
894 user_buf, count, ppos);
897 static ssize_t iwl_legacy_dbgfs_ucode_tx_stats_read(struct file *file,
898 char __user *user_buf,
899 size_t count, loff_t *ppos)
901 struct iwl_priv *priv = file->private_data;
902 return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
903 user_buf, count, ppos);
906 static ssize_t iwl_legacy_dbgfs_ucode_general_stats_read(struct file *file,
907 char __user *user_buf,
908 size_t count, loff_t *ppos)
910 struct iwl_priv *priv = file->private_data;
911 return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
912 user_buf, count, ppos);
915 static ssize_t iwl_legacy_dbgfs_sensitivity_read(struct file *file,
916 char __user *user_buf,
917 size_t count, loff_t *ppos) {
919 struct iwl_priv *priv = file->private_data;
920 int pos = 0;
921 int cnt = 0;
922 char *buf;
923 int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
924 ssize_t ret;
925 struct iwl_sensitivity_data *data;
927 data = &priv->sensitivity_data;
928 buf = kzalloc(bufsz, GFP_KERNEL);
929 if (!buf) {
930 IWL_ERR(priv, "Can not allocate Buffer\n");
931 return -ENOMEM;
934 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
935 data->auto_corr_ofdm);
936 pos += scnprintf(buf + pos, bufsz - pos,
937 "auto_corr_ofdm_mrc:\t\t %u\n",
938 data->auto_corr_ofdm_mrc);
939 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
940 data->auto_corr_ofdm_x1);
941 pos += scnprintf(buf + pos, bufsz - pos,
942 "auto_corr_ofdm_mrc_x1:\t\t %u\n",
943 data->auto_corr_ofdm_mrc_x1);
944 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
945 data->auto_corr_cck);
946 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
947 data->auto_corr_cck_mrc);
948 pos += scnprintf(buf + pos, bufsz - pos,
949 "last_bad_plcp_cnt_ofdm:\t\t %u\n",
950 data->last_bad_plcp_cnt_ofdm);
951 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
952 data->last_fa_cnt_ofdm);
953 pos += scnprintf(buf + pos, bufsz - pos,
954 "last_bad_plcp_cnt_cck:\t\t %u\n",
955 data->last_bad_plcp_cnt_cck);
956 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
957 data->last_fa_cnt_cck);
958 pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
959 data->nrg_curr_state);
960 pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
961 data->nrg_prev_state);
962 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
963 for (cnt = 0; cnt < 10; cnt++) {
964 pos += scnprintf(buf + pos, bufsz - pos, " %u",
965 data->nrg_value[cnt]);
967 pos += scnprintf(buf + pos, bufsz - pos, "\n");
968 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
969 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
970 pos += scnprintf(buf + pos, bufsz - pos, " %u",
971 data->nrg_silence_rssi[cnt]);
973 pos += scnprintf(buf + pos, bufsz - pos, "\n");
974 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
975 data->nrg_silence_ref);
976 pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
977 data->nrg_energy_idx);
978 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
979 data->nrg_silence_idx);
980 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
981 data->nrg_th_cck);
982 pos += scnprintf(buf + pos, bufsz - pos,
983 "nrg_auto_corr_silence_diff:\t %u\n",
984 data->nrg_auto_corr_silence_diff);
985 pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
986 data->num_in_cck_no_fa);
987 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
988 data->nrg_th_ofdm);
990 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
991 kfree(buf);
992 return ret;
996 static ssize_t iwl_legacy_dbgfs_chain_noise_read(struct file *file,
997 char __user *user_buf,
998 size_t count, loff_t *ppos) {
1000 struct iwl_priv *priv = file->private_data;
1001 int pos = 0;
1002 int cnt = 0;
1003 char *buf;
1004 int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
1005 ssize_t ret;
1006 struct iwl_chain_noise_data *data;
1008 data = &priv->chain_noise_data;
1009 buf = kzalloc(bufsz, GFP_KERNEL);
1010 if (!buf) {
1011 IWL_ERR(priv, "Can not allocate Buffer\n");
1012 return -ENOMEM;
1015 pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1016 data->active_chains);
1017 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1018 data->chain_noise_a);
1019 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1020 data->chain_noise_b);
1021 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1022 data->chain_noise_c);
1023 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1024 data->chain_signal_a);
1025 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1026 data->chain_signal_b);
1027 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1028 data->chain_signal_c);
1029 pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1030 data->beacon_count);
1032 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1033 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1034 pos += scnprintf(buf + pos, bufsz - pos, " %u",
1035 data->disconn_array[cnt]);
1037 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1038 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1039 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1040 pos += scnprintf(buf + pos, bufsz - pos, " %u",
1041 data->delta_gain_code[cnt]);
1043 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1044 pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1045 data->radio_write);
1046 pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1047 data->state);
1049 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1050 kfree(buf);
1051 return ret;
1054 static ssize_t iwl_legacy_dbgfs_power_save_status_read(struct file *file,
1055 char __user *user_buf,
1056 size_t count, loff_t *ppos)
1058 struct iwl_priv *priv = file->private_data;
1059 char buf[60];
1060 int pos = 0;
1061 const size_t bufsz = sizeof(buf);
1062 u32 pwrsave_status;
1064 pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
1065 CSR_GP_REG_POWER_SAVE_STATUS_MSK;
1067 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
1068 pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
1069 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
1070 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
1071 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
1072 "error");
1074 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1077 static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,
1078 const char __user *user_buf,
1079 size_t count, loff_t *ppos)
1081 struct iwl_priv *priv = file->private_data;
1082 char buf[8];
1083 int buf_size;
1084 int clear;
1086 memset(buf, 0, sizeof(buf));
1087 buf_size = min(count, sizeof(buf) - 1);
1088 if (copy_from_user(buf, user_buf, buf_size))
1089 return -EFAULT;
1090 if (sscanf(buf, "%d", &clear) != 1)
1091 return -EFAULT;
1093 /* make request to uCode to retrieve statistics information */
1094 mutex_lock(&priv->mutex);
1095 iwl_legacy_send_statistics_request(priv, CMD_SYNC, true);
1096 mutex_unlock(&priv->mutex);
1098 return count;
1101 static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
1102 char __user *user_buf,
1103 size_t count, loff_t *ppos) {
1105 struct iwl_priv *priv = file->private_data;
1106 int pos = 0;
1107 char buf[128];
1108 const size_t bufsz = sizeof(buf);
1110 pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
1111 priv->event_log.ucode_trace ? "On" : "Off");
1112 pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
1113 priv->event_log.non_wraps_count);
1114 pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
1115 priv->event_log.wraps_once_count);
1116 pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
1117 priv->event_log.wraps_more_count);
1119 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1122 static ssize_t iwl_legacy_dbgfs_ucode_tracing_write(struct file *file,
1123 const char __user *user_buf,
1124 size_t count, loff_t *ppos)
1126 struct iwl_priv *priv = file->private_data;
1127 char buf[8];
1128 int buf_size;
1129 int trace;
1131 memset(buf, 0, sizeof(buf));
1132 buf_size = min(count, sizeof(buf) - 1);
1133 if (copy_from_user(buf, user_buf, buf_size))
1134 return -EFAULT;
1135 if (sscanf(buf, "%d", &trace) != 1)
1136 return -EFAULT;
1138 if (trace) {
1139 priv->event_log.ucode_trace = true;
1140 /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
1141 mod_timer(&priv->ucode_trace,
1142 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
1143 } else {
1144 priv->event_log.ucode_trace = false;
1145 del_timer_sync(&priv->ucode_trace);
1148 return count;
1151 static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
1152 char __user *user_buf,
1153 size_t count, loff_t *ppos) {
1155 struct iwl_priv *priv = file->private_data;
1156 int len = 0;
1157 char buf[20];
1159 len = sprintf(buf, "0x%04X\n",
1160 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
1161 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1164 static ssize_t iwl_legacy_dbgfs_rxon_filter_flags_read(struct file *file,
1165 char __user *user_buf,
1166 size_t count, loff_t *ppos) {
1168 struct iwl_priv *priv = file->private_data;
1169 int len = 0;
1170 char buf[20];
1172 len = sprintf(buf, "0x%04X\n",
1173 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
1174 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1177 static ssize_t iwl_legacy_dbgfs_fh_reg_read(struct file *file,
1178 char __user *user_buf,
1179 size_t count, loff_t *ppos)
1181 struct iwl_priv *priv = file->private_data;
1182 char *buf;
1183 int pos = 0;
1184 ssize_t ret = -EFAULT;
1186 if (priv->cfg->ops->lib->dump_fh) {
1187 ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
1188 if (buf) {
1189 ret = simple_read_from_buffer(user_buf,
1190 count, ppos, buf, pos);
1191 kfree(buf);
1195 return ret;
1198 static ssize_t iwl_legacy_dbgfs_missed_beacon_read(struct file *file,
1199 char __user *user_buf,
1200 size_t count, loff_t *ppos) {
1202 struct iwl_priv *priv = file->private_data;
1203 int pos = 0;
1204 char buf[12];
1205 const size_t bufsz = sizeof(buf);
1207 pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
1208 priv->missed_beacon_threshold);
1210 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1213 static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,
1214 const char __user *user_buf,
1215 size_t count, loff_t *ppos)
1217 struct iwl_priv *priv = file->private_data;
1218 char buf[8];
1219 int buf_size;
1220 int missed;
1222 memset(buf, 0, sizeof(buf));
1223 buf_size = min(count, sizeof(buf) - 1);
1224 if (copy_from_user(buf, user_buf, buf_size))
1225 return -EFAULT;
1226 if (sscanf(buf, "%d", &missed) != 1)
1227 return -EINVAL;
1229 if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
1230 missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
1231 priv->missed_beacon_threshold =
1232 IWL_MISSED_BEACON_THRESHOLD_DEF;
1233 else
1234 priv->missed_beacon_threshold = missed;
1236 return count;
1239 static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
1240 char __user *user_buf,
1241 size_t count, loff_t *ppos) {
1243 struct iwl_priv *priv = file->private_data;
1244 int pos = 0;
1245 char buf[12];
1246 const size_t bufsz = sizeof(buf);
1248 pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
1249 priv->cfg->base_params->plcp_delta_threshold);
1251 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1254 static ssize_t iwl_legacy_dbgfs_plcp_delta_write(struct file *file,
1255 const char __user *user_buf,
1256 size_t count, loff_t *ppos) {
1258 struct iwl_priv *priv = file->private_data;
1259 char buf[8];
1260 int buf_size;
1261 int plcp;
1263 memset(buf, 0, sizeof(buf));
1264 buf_size = min(count, sizeof(buf) - 1);
1265 if (copy_from_user(buf, user_buf, buf_size))
1266 return -EFAULT;
1267 if (sscanf(buf, "%d", &plcp) != 1)
1268 return -EINVAL;
1269 if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
1270 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
1271 priv->cfg->base_params->plcp_delta_threshold =
1272 IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
1273 else
1274 priv->cfg->base_params->plcp_delta_threshold = plcp;
1275 return count;
1278 static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
1279 char __user *user_buf,
1280 size_t count, loff_t *ppos) {
1282 struct iwl_priv *priv = file->private_data;
1283 int i, pos = 0;
1284 char buf[300];
1285 const size_t bufsz = sizeof(buf);
1286 struct iwl_force_reset *force_reset;
1288 for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
1289 force_reset = &priv->force_reset[i];
1290 pos += scnprintf(buf + pos, bufsz - pos,
1291 "Force reset method %d\n", i);
1292 pos += scnprintf(buf + pos, bufsz - pos,
1293 "\tnumber of reset request: %d\n",
1294 force_reset->reset_request_count);
1295 pos += scnprintf(buf + pos, bufsz - pos,
1296 "\tnumber of reset request success: %d\n",
1297 force_reset->reset_success_count);
1298 pos += scnprintf(buf + pos, bufsz - pos,
1299 "\tnumber of reset request reject: %d\n",
1300 force_reset->reset_reject_count);
1301 pos += scnprintf(buf + pos, bufsz - pos,
1302 "\treset duration: %lu\n",
1303 force_reset->reset_duration);
1305 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1308 static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,
1309 const char __user *user_buf,
1310 size_t count, loff_t *ppos) {
1312 struct iwl_priv *priv = file->private_data;
1313 char buf[8];
1314 int buf_size;
1315 int reset, ret;
1317 memset(buf, 0, sizeof(buf));
1318 buf_size = min(count, sizeof(buf) - 1);
1319 if (copy_from_user(buf, user_buf, buf_size))
1320 return -EFAULT;
1321 if (sscanf(buf, "%d", &reset) != 1)
1322 return -EINVAL;
1323 switch (reset) {
1324 case IWL_RF_RESET:
1325 case IWL_FW_RESET:
1326 ret = iwl_legacy_force_reset(priv, reset, true);
1327 break;
1328 default:
1329 return -EINVAL;
1331 return ret ? ret : count;
1334 static ssize_t iwl_legacy_dbgfs_wd_timeout_write(struct file *file,
1335 const char __user *user_buf,
1336 size_t count, loff_t *ppos) {
1338 struct iwl_priv *priv = file->private_data;
1339 char buf[8];
1340 int buf_size;
1341 int timeout;
1343 memset(buf, 0, sizeof(buf));
1344 buf_size = min(count, sizeof(buf) - 1);
1345 if (copy_from_user(buf, user_buf, buf_size))
1346 return -EFAULT;
1347 if (sscanf(buf, "%d", &timeout) != 1)
1348 return -EINVAL;
1349 if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
1350 timeout = IWL_DEF_WD_TIMEOUT;
1352 priv->cfg->base_params->wd_timeout = timeout;
1353 iwl_legacy_setup_watchdog(priv);
1354 return count;
1357 DEBUGFS_READ_FILE_OPS(rx_statistics);
1358 DEBUGFS_READ_FILE_OPS(tx_statistics);
1359 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1360 DEBUGFS_READ_FILE_OPS(rx_queue);
1361 DEBUGFS_READ_FILE_OPS(tx_queue);
1362 DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1363 DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1364 DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1365 DEBUGFS_READ_FILE_OPS(sensitivity);
1366 DEBUGFS_READ_FILE_OPS(chain_noise);
1367 DEBUGFS_READ_FILE_OPS(power_save_status);
1368 DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
1369 DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
1370 DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
1371 DEBUGFS_READ_FILE_OPS(fh_reg);
1372 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
1373 DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
1374 DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
1375 DEBUGFS_READ_FILE_OPS(rxon_flags);
1376 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1377 DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1380 * Create the debugfs files and directories
1383 int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
1385 struct dentry *phyd = priv->hw->wiphy->debugfsdir;
1386 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
1388 dir_drv = debugfs_create_dir(name, phyd);
1389 if (!dir_drv)
1390 return -ENOMEM;
1392 priv->debugfs_dir = dir_drv;
1394 dir_data = debugfs_create_dir("data", dir_drv);
1395 if (!dir_data)
1396 goto err;
1397 dir_rf = debugfs_create_dir("rf", dir_drv);
1398 if (!dir_rf)
1399 goto err;
1400 dir_debug = debugfs_create_dir("debug", dir_drv);
1401 if (!dir_debug)
1402 goto err;
1404 DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
1405 DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
1406 DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
1407 DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
1408 DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
1409 DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
1410 DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
1411 DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
1412 DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
1413 DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
1414 DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
1415 DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
1416 DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
1417 DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
1418 DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
1419 DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
1420 DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
1421 DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
1422 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
1423 DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
1424 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
1425 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
1426 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
1427 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
1429 if (priv->cfg->base_params->sensitivity_calib_by_driver)
1430 DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
1431 if (priv->cfg->base_params->chain_noise_calib_by_driver)
1432 DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
1433 if (priv->cfg->base_params->ucode_tracing)
1434 DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
1435 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
1436 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
1437 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
1438 if (priv->cfg->base_params->sensitivity_calib_by_driver)
1439 DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
1440 &priv->disable_sens_cal);
1441 if (priv->cfg->base_params->chain_noise_calib_by_driver)
1442 DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
1443 &priv->disable_chain_noise_cal);
1444 DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
1445 &priv->disable_tx_power_cal);
1446 return 0;
1448 err:
1449 IWL_ERR(priv, "Can't create the debugfs directory\n");
1450 iwl_legacy_dbgfs_unregister(priv);
1451 return -ENOMEM;
1453 EXPORT_SYMBOL(iwl_legacy_dbgfs_register);
1456 * Remove the debugfs files and directories
1459 void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv)
1461 if (!priv->debugfs_dir)
1462 return;
1464 debugfs_remove_recursive(priv->debugfs_dir);
1465 priv->debugfs_dir = NULL;
1467 EXPORT_SYMBOL(iwl_legacy_dbgfs_unregister);