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