iwlwifi: remove CMD_SYNC
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / iwlwifi / mvm / debugfs.c
1 /******************************************************************************
2  *
3  * This file is provided under a dual BSD/GPLv2 license.  When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * GPL LICENSE SUMMARY
7  *
8  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of version 2 of the GNU General Public License as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22  * USA
23  *
24  * The full GNU General Public License is included in this distribution
25  * in the file called COPYING.
26  *
27  * Contact Information:
28  *  Intel Linux Wireless <ilw@linux.intel.com>
29  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30  *
31  * BSD LICENSE
32  *
33  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  *
40  *  * Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  *  * Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in
44  *    the documentation and/or other materials provided with the
45  *    distribution.
46  *  * Neither the name Intel Corporation nor the names of its
47  *    contributors may be used to endorse or promote products derived
48  *    from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  *****************************************************************************/
63 #include <linux/vmalloc.h>
64
65 #include "mvm.h"
66 #include "sta.h"
67 #include "iwl-io.h"
68 #include "iwl-prph.h"
69 #include "debugfs.h"
70 #include "iwl-fw-error-dump.h"
71
72 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
73                                         size_t count, loff_t *ppos)
74 {
75         int ret;
76         u32 scd_q_msk;
77
78         if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
79                 return -EIO;
80
81         if (sscanf(buf, "%x", &scd_q_msk) != 1)
82                 return -EINVAL;
83
84         IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
85
86         mutex_lock(&mvm->mutex);
87         ret =  iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count;
88         mutex_unlock(&mvm->mutex);
89
90         return ret;
91 }
92
93 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
94                                          size_t count, loff_t *ppos)
95 {
96         struct iwl_mvm_sta *mvmsta;
97         int sta_id, drain, ret;
98
99         if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
100                 return -EIO;
101
102         if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
103                 return -EINVAL;
104         if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
105                 return -EINVAL;
106         if (drain < 0 || drain > 1)
107                 return -EINVAL;
108
109         mutex_lock(&mvm->mutex);
110
111         mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
112
113         if (!mvmsta)
114                 ret = -ENOENT;
115         else
116                 ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
117
118         mutex_unlock(&mvm->mutex);
119
120         return ret;
121 }
122
123 static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
124 {
125         struct iwl_mvm *mvm = inode->i_private;
126         int ret;
127
128         if (!mvm)
129                 return -EINVAL;
130
131         mutex_lock(&mvm->mutex);
132         if (!mvm->fw_error_dump) {
133                 ret = -ENODATA;
134                 goto out;
135         }
136
137         file->private_data = mvm->fw_error_dump;
138         mvm->fw_error_dump = NULL;
139         ret = 0;
140
141 out:
142         mutex_unlock(&mvm->mutex);
143         return ret;
144 }
145
146 static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
147                                             char __user *user_buf,
148                                             size_t count, loff_t *ppos)
149 {
150         struct iwl_fw_error_dump_file *dump_file = file->private_data;
151
152         return simple_read_from_buffer(user_buf, count, ppos,
153                                        dump_file,
154                                        le32_to_cpu(dump_file->file_len));
155 }
156
157 static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
158                                            struct file *file)
159 {
160         vfree(file->private_data);
161
162         return 0;
163 }
164
165 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
166                                    size_t count, loff_t *ppos)
167 {
168         struct iwl_mvm *mvm = file->private_data;
169         const struct fw_img *img;
170         unsigned int ofs, len;
171         size_t ret;
172         u8 *ptr;
173
174         if (!mvm->ucode_loaded)
175                 return -EINVAL;
176
177         /* default is to dump the entire data segment */
178         img = &mvm->fw->img[mvm->cur_ucode];
179         ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
180         len = img->sec[IWL_UCODE_SECTION_DATA].len;
181
182         if (mvm->dbgfs_sram_len) {
183                 ofs = mvm->dbgfs_sram_offset;
184                 len = mvm->dbgfs_sram_len;
185         }
186
187         ptr = kzalloc(len, GFP_KERNEL);
188         if (!ptr)
189                 return -ENOMEM;
190
191         iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
192
193         ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
194
195         kfree(ptr);
196
197         return ret;
198 }
199
200 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
201                                     size_t count, loff_t *ppos)
202 {
203         const struct fw_img *img;
204         u32 offset, len;
205         u32 img_offset, img_len;
206
207         if (!mvm->ucode_loaded)
208                 return -EINVAL;
209
210         img = &mvm->fw->img[mvm->cur_ucode];
211         img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
212         img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
213
214         if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
215                 if ((offset & 0x3) || (len & 0x3))
216                         return -EINVAL;
217
218                 if (offset + len > img_offset + img_len)
219                         return -EINVAL;
220
221                 mvm->dbgfs_sram_offset = offset;
222                 mvm->dbgfs_sram_len = len;
223         } else {
224                 mvm->dbgfs_sram_offset = 0;
225                 mvm->dbgfs_sram_len = 0;
226         }
227
228         return count;
229 }
230
231 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
232                                        size_t count, loff_t *ppos)
233 {
234         struct iwl_mvm *mvm = file->private_data;
235         struct ieee80211_sta *sta;
236         char buf[400];
237         int i, pos = 0, bufsz = sizeof(buf);
238
239         mutex_lock(&mvm->mutex);
240
241         for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
242                 pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
243                 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
244                                                 lockdep_is_held(&mvm->mutex));
245                 if (!sta)
246                         pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
247                 else if (IS_ERR(sta))
248                         pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
249                                          PTR_ERR(sta));
250                 else
251                         pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
252                                          sta->addr);
253         }
254
255         mutex_unlock(&mvm->mutex);
256
257         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
258 }
259
260 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
261                                                 char __user *user_buf,
262                                                 size_t count, loff_t *ppos)
263 {
264         struct iwl_mvm *mvm = file->private_data;
265         char buf[64];
266         int bufsz = sizeof(buf);
267         int pos = 0;
268
269         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
270                          mvm->disable_power_off);
271         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
272                          mvm->disable_power_off_d3);
273
274         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
275 }
276
277 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
278                                                  size_t count, loff_t *ppos)
279 {
280         int ret, val;
281
282         if (!mvm->ucode_loaded)
283                 return -EIO;
284
285         if (!strncmp("disable_power_off_d0=", buf, 21)) {
286                 if (sscanf(buf + 21, "%d", &val) != 1)
287                         return -EINVAL;
288                 mvm->disable_power_off = val;
289         } else if (!strncmp("disable_power_off_d3=", buf, 21)) {
290                 if (sscanf(buf + 21, "%d", &val) != 1)
291                         return -EINVAL;
292                 mvm->disable_power_off_d3 = val;
293         } else {
294                 return -EINVAL;
295         }
296
297         mutex_lock(&mvm->mutex);
298         ret = iwl_mvm_power_update_device(mvm);
299         mutex_unlock(&mvm->mutex);
300
301         return ret ?: count;
302 }
303
304 #define BT_MBOX_MSG(_notif, _num, _field)                                    \
305         ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
306         >> BT_MBOX##_num##_##_field##_POS)
307
308
309 #define BT_MBOX_PRINT(_num, _field, _end)                                   \
310                         pos += scnprintf(buf + pos, bufsz - pos,            \
311                                          "\t%s: %d%s",                      \
312                                          #_field,                           \
313                                          BT_MBOX_MSG(notif, _num, _field),  \
314                                          true ? "\n" : ", ");
315
316 static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
317                                        size_t count, loff_t *ppos)
318 {
319         struct iwl_mvm *mvm = file->private_data;
320         struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
321         char *buf;
322         int ret, pos = 0, bufsz = sizeof(char) * 1024;
323
324         buf = kmalloc(bufsz, GFP_KERNEL);
325         if (!buf)
326                 return -ENOMEM;
327
328         mutex_lock(&mvm->mutex);
329
330         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
331
332         BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
333         BT_MBOX_PRINT(0, LE_PROF1, false);
334         BT_MBOX_PRINT(0, LE_PROF2, false);
335         BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
336         BT_MBOX_PRINT(0, CHL_SEQ_N, false);
337         BT_MBOX_PRINT(0, INBAND_S, false);
338         BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
339         BT_MBOX_PRINT(0, LE_SCAN, false);
340         BT_MBOX_PRINT(0, LE_ADV, false);
341         BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
342         BT_MBOX_PRINT(0, OPEN_CON_1, true);
343
344         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
345
346         BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
347         BT_MBOX_PRINT(1, IP_SR, false);
348         BT_MBOX_PRINT(1, LE_MSTR, false);
349         BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
350         BT_MBOX_PRINT(1, MSG_TYPE, false);
351         BT_MBOX_PRINT(1, SSN, true);
352
353         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
354
355         BT_MBOX_PRINT(2, SNIFF_ACT, false);
356         BT_MBOX_PRINT(2, PAG, false);
357         BT_MBOX_PRINT(2, INQUIRY, false);
358         BT_MBOX_PRINT(2, CONN, false);
359         BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
360         BT_MBOX_PRINT(2, DISC, false);
361         BT_MBOX_PRINT(2, SCO_TX_ACT, false);
362         BT_MBOX_PRINT(2, SCO_RX_ACT, false);
363         BT_MBOX_PRINT(2, ESCO_RE_TX, false);
364         BT_MBOX_PRINT(2, SCO_DURATION, true);
365
366         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
367
368         BT_MBOX_PRINT(3, SCO_STATE, false);
369         BT_MBOX_PRINT(3, SNIFF_STATE, false);
370         BT_MBOX_PRINT(3, A2DP_STATE, false);
371         BT_MBOX_PRINT(3, ACL_STATE, false);
372         BT_MBOX_PRINT(3, MSTR_STATE, false);
373         BT_MBOX_PRINT(3, OBX_STATE, false);
374         BT_MBOX_PRINT(3, OPEN_CON_2, false);
375         BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
376         BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
377         BT_MBOX_PRINT(3, INBAND_P, false);
378         BT_MBOX_PRINT(3, MSG_TYPE_2, false);
379         BT_MBOX_PRINT(3, SSN_2, false);
380         BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
381
382         pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n",
383                          notif->bt_status);
384         pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n",
385                          notif->bt_open_conn);
386         pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n",
387                          notif->bt_traffic_load);
388         pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n",
389                          notif->bt_agg_traffic_load);
390         pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
391                          notif->bt_ci_compliance);
392         pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
393                          le32_to_cpu(notif->primary_ch_lut));
394         pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
395                          le32_to_cpu(notif->secondary_ch_lut));
396         pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n",
397                          le32_to_cpu(notif->bt_activity_grading));
398         pos += scnprintf(buf+pos, bufsz-pos,
399                          "antenna isolation = %d CORUN LUT index = %d\n",
400                          mvm->last_ant_isol, mvm->last_corun_lut);
401
402         mutex_unlock(&mvm->mutex);
403
404         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
405         kfree(buf);
406
407         return ret;
408 }
409 #undef BT_MBOX_PRINT
410
411 static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
412                                      size_t count, loff_t *ppos)
413 {
414         struct iwl_mvm *mvm = file->private_data;
415         struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
416         char buf[256];
417         int bufsz = sizeof(buf);
418         int pos = 0;
419
420         mutex_lock(&mvm->mutex);
421
422         pos += scnprintf(buf+pos, bufsz-pos, "Channel inhibition CMD\n");
423         pos += scnprintf(buf+pos, bufsz-pos,
424                        "\tPrimary Channel Bitmap 0x%016llx Fat: %d\n",
425                        le64_to_cpu(cmd->bt_primary_ci),
426                        !!cmd->co_run_bw_primary);
427         pos += scnprintf(buf+pos, bufsz-pos,
428                        "\tSecondary Channel Bitmap 0x%016llx Fat: %d\n",
429                        le64_to_cpu(cmd->bt_secondary_ci),
430                        !!cmd->co_run_bw_secondary);
431
432         pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
433         pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
434                          iwl_bt_ack_kill_msk[mvm->bt_kill_msk]);
435         pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
436                          iwl_bt_cts_kill_msk[mvm->bt_kill_msk]);
437
438         mutex_unlock(&mvm->mutex);
439
440         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
441 }
442
443 static ssize_t
444 iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
445                            size_t count, loff_t *ppos)
446 {
447         u32 bt_tx_prio;
448
449         if (sscanf(buf, "%u", &bt_tx_prio) != 1)
450                 return -EINVAL;
451         if (bt_tx_prio > 4)
452                 return -EINVAL;
453
454         mvm->bt_tx_prio = bt_tx_prio;
455
456         return count;
457 }
458
459 #define PRINT_STATS_LE32(_str, _val)                                    \
460                          pos += scnprintf(buf + pos, bufsz - pos,       \
461                                           fmt_table, _str,              \
462                                           le32_to_cpu(_val))
463
464 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
465                                           char __user *user_buf, size_t count,
466                                           loff_t *ppos)
467 {
468         struct iwl_mvm *mvm = file->private_data;
469         static const char *fmt_table = "\t%-30s %10u\n";
470         static const char *fmt_header = "%-32s\n";
471         int pos = 0;
472         char *buf;
473         int ret;
474         /* 43 is the size of each data line, 33 is the size of each header */
475         size_t bufsz =
476                 ((sizeof(struct mvm_statistics_rx) / sizeof(__le32)) * 43) +
477                 (4 * 33) + 1;
478
479         struct mvm_statistics_rx_phy *ofdm;
480         struct mvm_statistics_rx_phy *cck;
481         struct mvm_statistics_rx_non_phy *general;
482         struct mvm_statistics_rx_ht_phy *ht;
483
484         buf = kzalloc(bufsz, GFP_KERNEL);
485         if (!buf)
486                 return -ENOMEM;
487
488         mutex_lock(&mvm->mutex);
489
490         ofdm = &mvm->rx_stats.ofdm;
491         cck = &mvm->rx_stats.cck;
492         general = &mvm->rx_stats.general;
493         ht = &mvm->rx_stats.ofdm_ht;
494
495         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
496                          "Statistics_Rx - OFDM");
497         PRINT_STATS_LE32("ina_cnt", ofdm->ina_cnt);
498         PRINT_STATS_LE32("fina_cnt", ofdm->fina_cnt);
499         PRINT_STATS_LE32("plcp_err", ofdm->plcp_err);
500         PRINT_STATS_LE32("crc32_err", ofdm->crc32_err);
501         PRINT_STATS_LE32("overrun_err", ofdm->overrun_err);
502         PRINT_STATS_LE32("early_overrun_err", ofdm->early_overrun_err);
503         PRINT_STATS_LE32("crc32_good", ofdm->crc32_good);
504         PRINT_STATS_LE32("false_alarm_cnt", ofdm->false_alarm_cnt);
505         PRINT_STATS_LE32("fina_sync_err_cnt", ofdm->fina_sync_err_cnt);
506         PRINT_STATS_LE32("sfd_timeout", ofdm->sfd_timeout);
507         PRINT_STATS_LE32("fina_timeout", ofdm->fina_timeout);
508         PRINT_STATS_LE32("unresponded_rts", ofdm->unresponded_rts);
509         PRINT_STATS_LE32("rxe_frame_lmt_overrun",
510                          ofdm->rxe_frame_limit_overrun);
511         PRINT_STATS_LE32("sent_ack_cnt", ofdm->sent_ack_cnt);
512         PRINT_STATS_LE32("sent_cts_cnt", ofdm->sent_cts_cnt);
513         PRINT_STATS_LE32("sent_ba_rsp_cnt", ofdm->sent_ba_rsp_cnt);
514         PRINT_STATS_LE32("dsp_self_kill", ofdm->dsp_self_kill);
515         PRINT_STATS_LE32("mh_format_err", ofdm->mh_format_err);
516         PRINT_STATS_LE32("re_acq_main_rssi_sum", ofdm->re_acq_main_rssi_sum);
517         PRINT_STATS_LE32("reserved", ofdm->reserved);
518
519         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
520                          "Statistics_Rx - CCK");
521         PRINT_STATS_LE32("ina_cnt", cck->ina_cnt);
522         PRINT_STATS_LE32("fina_cnt", cck->fina_cnt);
523         PRINT_STATS_LE32("plcp_err", cck->plcp_err);
524         PRINT_STATS_LE32("crc32_err", cck->crc32_err);
525         PRINT_STATS_LE32("overrun_err", cck->overrun_err);
526         PRINT_STATS_LE32("early_overrun_err", cck->early_overrun_err);
527         PRINT_STATS_LE32("crc32_good", cck->crc32_good);
528         PRINT_STATS_LE32("false_alarm_cnt", cck->false_alarm_cnt);
529         PRINT_STATS_LE32("fina_sync_err_cnt", cck->fina_sync_err_cnt);
530         PRINT_STATS_LE32("sfd_timeout", cck->sfd_timeout);
531         PRINT_STATS_LE32("fina_timeout", cck->fina_timeout);
532         PRINT_STATS_LE32("unresponded_rts", cck->unresponded_rts);
533         PRINT_STATS_LE32("rxe_frame_lmt_overrun",
534                          cck->rxe_frame_limit_overrun);
535         PRINT_STATS_LE32("sent_ack_cnt", cck->sent_ack_cnt);
536         PRINT_STATS_LE32("sent_cts_cnt", cck->sent_cts_cnt);
537         PRINT_STATS_LE32("sent_ba_rsp_cnt", cck->sent_ba_rsp_cnt);
538         PRINT_STATS_LE32("dsp_self_kill", cck->dsp_self_kill);
539         PRINT_STATS_LE32("mh_format_err", cck->mh_format_err);
540         PRINT_STATS_LE32("re_acq_main_rssi_sum", cck->re_acq_main_rssi_sum);
541         PRINT_STATS_LE32("reserved", cck->reserved);
542
543         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
544                          "Statistics_Rx - GENERAL");
545         PRINT_STATS_LE32("bogus_cts", general->bogus_cts);
546         PRINT_STATS_LE32("bogus_ack", general->bogus_ack);
547         PRINT_STATS_LE32("non_bssid_frames", general->non_bssid_frames);
548         PRINT_STATS_LE32("filtered_frames", general->filtered_frames);
549         PRINT_STATS_LE32("non_channel_beacons", general->non_channel_beacons);
550         PRINT_STATS_LE32("channel_beacons", general->channel_beacons);
551         PRINT_STATS_LE32("num_missed_bcon", general->num_missed_bcon);
552         PRINT_STATS_LE32("adc_rx_saturation_time",
553                          general->adc_rx_saturation_time);
554         PRINT_STATS_LE32("ina_detection_search_time",
555                          general->ina_detection_search_time);
556         PRINT_STATS_LE32("beacon_silence_rssi_a",
557                          general->beacon_silence_rssi_a);
558         PRINT_STATS_LE32("beacon_silence_rssi_b",
559                          general->beacon_silence_rssi_b);
560         PRINT_STATS_LE32("beacon_silence_rssi_c",
561                          general->beacon_silence_rssi_c);
562         PRINT_STATS_LE32("interference_data_flag",
563                          general->interference_data_flag);
564         PRINT_STATS_LE32("channel_load", general->channel_load);
565         PRINT_STATS_LE32("dsp_false_alarms", general->dsp_false_alarms);
566         PRINT_STATS_LE32("beacon_rssi_a", general->beacon_rssi_a);
567         PRINT_STATS_LE32("beacon_rssi_b", general->beacon_rssi_b);
568         PRINT_STATS_LE32("beacon_rssi_c", general->beacon_rssi_c);
569         PRINT_STATS_LE32("beacon_energy_a", general->beacon_energy_a);
570         PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b);
571         PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c);
572         PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills);
573         PRINT_STATS_LE32("mac_id", general->mac_id);
574         PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu);
575
576         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
577                          "Statistics_Rx - HT");
578         PRINT_STATS_LE32("plcp_err", ht->plcp_err);
579         PRINT_STATS_LE32("overrun_err", ht->overrun_err);
580         PRINT_STATS_LE32("early_overrun_err", ht->early_overrun_err);
581         PRINT_STATS_LE32("crc32_good", ht->crc32_good);
582         PRINT_STATS_LE32("crc32_err", ht->crc32_err);
583         PRINT_STATS_LE32("mh_format_err", ht->mh_format_err);
584         PRINT_STATS_LE32("agg_crc32_good", ht->agg_crc32_good);
585         PRINT_STATS_LE32("agg_mpdu_cnt", ht->agg_mpdu_cnt);
586         PRINT_STATS_LE32("agg_cnt", ht->agg_cnt);
587         PRINT_STATS_LE32("unsupport_mcs", ht->unsupport_mcs);
588
589         mutex_unlock(&mvm->mutex);
590
591         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
592         kfree(buf);
593
594         return ret;
595 }
596 #undef PRINT_STAT_LE32
597
598 static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
599                                           char __user *user_buf, size_t count,
600                                           loff_t *ppos,
601                                           struct iwl_mvm_frame_stats *stats)
602 {
603         char *buff, *pos, *endpos;
604         int idx, i;
605         int ret;
606         static const size_t bufsz = 1024;
607
608         buff = kmalloc(bufsz, GFP_KERNEL);
609         if (!buff)
610                 return -ENOMEM;
611
612         spin_lock_bh(&mvm->drv_stats_lock);
613
614         pos = buff;
615         endpos = pos + bufsz;
616
617         pos += scnprintf(pos, endpos - pos,
618                          "Legacy/HT/VHT\t:\t%d/%d/%d\n",
619                          stats->legacy_frames,
620                          stats->ht_frames,
621                          stats->vht_frames);
622         pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
623                          stats->bw_20_frames,
624                          stats->bw_40_frames,
625                          stats->bw_80_frames);
626         pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
627                          stats->ngi_frames,
628                          stats->sgi_frames);
629         pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
630                          stats->siso_frames,
631                          stats->mimo2_frames);
632         pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
633                          stats->fail_frames,
634                          stats->success_frames);
635         pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
636                          stats->agg_frames);
637         pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
638                          stats->ampdu_count);
639         pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
640                          stats->ampdu_count > 0 ?
641                          (stats->agg_frames / stats->ampdu_count) : 0);
642
643         pos += scnprintf(pos, endpos - pos, "Last Rates\n");
644
645         idx = stats->last_frame_idx - 1;
646         for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
647                 idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
648                 if (stats->last_rates[idx] == 0)
649                         continue;
650                 pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
651                                  (int)(ARRAY_SIZE(stats->last_rates) - i));
652                 pos += rs_pretty_print_rate(pos, stats->last_rates[idx]);
653         }
654         spin_unlock_bh(&mvm->drv_stats_lock);
655
656         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
657         kfree(buff);
658
659         return ret;
660 }
661
662 static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
663                                            char __user *user_buf, size_t count,
664                                            loff_t *ppos)
665 {
666         struct iwl_mvm *mvm = file->private_data;
667
668         return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
669                                           &mvm->drv_rx_stats);
670 }
671
672 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
673                                           size_t count, loff_t *ppos)
674 {
675         int ret;
676
677         mutex_lock(&mvm->mutex);
678
679         /* allow one more restart that we're provoking here */
680         if (mvm->restart_fw >= 0)
681                 mvm->restart_fw++;
682
683         /* take the return value to make compiler happy - it will fail anyway */
684         ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, 0, 0, NULL);
685
686         mutex_unlock(&mvm->mutex);
687
688         return count;
689 }
690
691 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
692                                       size_t count, loff_t *ppos)
693 {
694         iwl_write_prph(mvm->trans, DEVICE_SET_NMI_REG, 1);
695
696         return count;
697 }
698
699 static ssize_t
700 iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
701                                 char __user *user_buf,
702                                 size_t count, loff_t *ppos)
703 {
704         struct iwl_mvm *mvm = file->private_data;
705         int pos = 0;
706         char buf[32];
707         const size_t bufsz = sizeof(buf);
708
709         /* print which antennas were set for the scan command by the user */
710         pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
711         if (mvm->scan_rx_ant & ANT_A)
712                 pos += scnprintf(buf + pos, bufsz - pos, "A");
713         if (mvm->scan_rx_ant & ANT_B)
714                 pos += scnprintf(buf + pos, bufsz - pos, "B");
715         if (mvm->scan_rx_ant & ANT_C)
716                 pos += scnprintf(buf + pos, bufsz - pos, "C");
717         pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
718
719         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
720 }
721
722 static ssize_t
723 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
724                                  size_t count, loff_t *ppos)
725 {
726         u8 scan_rx_ant;
727
728         if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
729                 return -EINVAL;
730         if (scan_rx_ant > ANT_ABC)
731                 return -EINVAL;
732         if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
733                 return -EINVAL;
734
735         mvm->scan_rx_ant = scan_rx_ant;
736
737         return count;
738 }
739
740 #define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
741 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
742 static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
743                                             char __user *user_buf,
744                                             size_t count, loff_t *ppos)
745 {
746         struct iwl_mvm *mvm = file->private_data;
747         struct iwl_bcast_filter_cmd cmd;
748         const struct iwl_fw_bcast_filter *filter;
749         char *buf;
750         int bufsz = 1024;
751         int i, j, pos = 0;
752         ssize_t ret;
753
754         buf = kzalloc(bufsz, GFP_KERNEL);
755         if (!buf)
756                 return -ENOMEM;
757
758         mutex_lock(&mvm->mutex);
759         if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
760                 ADD_TEXT("None\n");
761                 mutex_unlock(&mvm->mutex);
762                 goto out;
763         }
764         mutex_unlock(&mvm->mutex);
765
766         for (i = 0; cmd.filters[i].attrs[0].mask; i++) {
767                 filter = &cmd.filters[i];
768
769                 ADD_TEXT("Filter [%d]:\n", i);
770                 ADD_TEXT("\tDiscard=%d\n", filter->discard);
771                 ADD_TEXT("\tFrame Type: %s\n",
772                          filter->frame_type ? "IPv4" : "Generic");
773
774                 for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) {
775                         const struct iwl_fw_bcast_filter_attr *attr;
776
777                         attr = &filter->attrs[j];
778                         if (!attr->mask)
779                                 break;
780
781                         ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n",
782                                  j, attr->offset,
783                                  attr->offset_type ? "IP End" :
784                                                      "Payload Start",
785                                  be32_to_cpu(attr->mask),
786                                  be32_to_cpu(attr->val),
787                                  le16_to_cpu(attr->reserved1));
788                 }
789         }
790 out:
791         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
792         kfree(buf);
793         return ret;
794 }
795
796 static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
797                                              size_t count, loff_t *ppos)
798 {
799         int pos, next_pos;
800         struct iwl_fw_bcast_filter filter = {};
801         struct iwl_bcast_filter_cmd cmd;
802         u32 filter_id, attr_id, mask, value;
803         int err = 0;
804
805         if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard,
806                    &filter.frame_type, &pos) != 3)
807                 return -EINVAL;
808
809         if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) ||
810             filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4)
811                 return -EINVAL;
812
813         for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs);
814              attr_id++) {
815                 struct iwl_fw_bcast_filter_attr *attr =
816                                 &filter.attrs[attr_id];
817
818                 if (pos >= count)
819                         break;
820
821                 if (sscanf(&buf[pos], "%hhi %hhi %i %i %n",
822                            &attr->offset, &attr->offset_type,
823                            &mask, &value, &next_pos) != 4)
824                         return -EINVAL;
825
826                 attr->mask = cpu_to_be32(mask);
827                 attr->val = cpu_to_be32(value);
828                 if (mask)
829                         filter.num_attrs++;
830
831                 pos += next_pos;
832         }
833
834         mutex_lock(&mvm->mutex);
835         memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id],
836                &filter, sizeof(filter));
837
838         /* send updated bcast filtering configuration */
839         if (mvm->dbgfs_bcast_filtering.override &&
840             iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
841                 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
842                                            sizeof(cmd), &cmd);
843         mutex_unlock(&mvm->mutex);
844
845         return err ?: count;
846 }
847
848 static ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file,
849                                                  char __user *user_buf,
850                                                  size_t count, loff_t *ppos)
851 {
852         struct iwl_mvm *mvm = file->private_data;
853         struct iwl_bcast_filter_cmd cmd;
854         char *buf;
855         int bufsz = 1024;
856         int i, pos = 0;
857         ssize_t ret;
858
859         buf = kzalloc(bufsz, GFP_KERNEL);
860         if (!buf)
861                 return -ENOMEM;
862
863         mutex_lock(&mvm->mutex);
864         if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
865                 ADD_TEXT("None\n");
866                 mutex_unlock(&mvm->mutex);
867                 goto out;
868         }
869         mutex_unlock(&mvm->mutex);
870
871         for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) {
872                 const struct iwl_fw_bcast_mac *mac = &cmd.macs[i];
873
874                 ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n",
875                          i, mac->default_discard, mac->attached_filters);
876         }
877 out:
878         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
879         kfree(buf);
880         return ret;
881 }
882
883 static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
884                                                   char *buf, size_t count,
885                                                   loff_t *ppos)
886 {
887         struct iwl_bcast_filter_cmd cmd;
888         struct iwl_fw_bcast_mac mac = {};
889         u32 mac_id, attached_filters;
890         int err = 0;
891
892         if (!mvm->bcast_filters)
893                 return -ENOENT;
894
895         if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard,
896                    &attached_filters) != 3)
897                 return -EINVAL;
898
899         if (mac_id >= ARRAY_SIZE(cmd.macs) ||
900             mac.default_discard > 1 ||
901             attached_filters >= BIT(ARRAY_SIZE(cmd.filters)))
902                 return -EINVAL;
903
904         mac.attached_filters = cpu_to_le16(attached_filters);
905
906         mutex_lock(&mvm->mutex);
907         memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id],
908                &mac, sizeof(mac));
909
910         /* send updated bcast filtering configuration */
911         if (mvm->dbgfs_bcast_filtering.override &&
912             iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
913                 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
914                                            sizeof(cmd), &cmd);
915         mutex_unlock(&mvm->mutex);
916
917         return err ?: count;
918 }
919 #endif
920
921 #ifdef CONFIG_PM_SLEEP
922 static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
923                                        size_t count, loff_t *ppos)
924 {
925         int store;
926
927         if (sscanf(buf, "%d", &store) != 1)
928                 return -EINVAL;
929
930         mvm->store_d3_resume_sram = store;
931
932         return count;
933 }
934
935 static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
936                                       size_t count, loff_t *ppos)
937 {
938         struct iwl_mvm *mvm = file->private_data;
939         const struct fw_img *img;
940         int ofs, len, pos = 0;
941         size_t bufsz, ret;
942         char *buf;
943         u8 *ptr = mvm->d3_resume_sram;
944
945         img = &mvm->fw->img[IWL_UCODE_WOWLAN];
946         len = img->sec[IWL_UCODE_SECTION_DATA].len;
947
948         bufsz = len * 4 + 256;
949         buf = kzalloc(bufsz, GFP_KERNEL);
950         if (!buf)
951                 return -ENOMEM;
952
953         pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n",
954                          mvm->store_d3_resume_sram ? "en" : "dis");
955
956         if (ptr) {
957                 for (ofs = 0; ofs < len; ofs += 16) {
958                         pos += scnprintf(buf + pos, bufsz - pos,
959                                          "0x%.4x ", ofs);
960                         hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos,
961                                            bufsz - pos, false);
962                         pos += strlen(buf + pos);
963                         if (bufsz - pos > 0)
964                                 buf[pos++] = '\n';
965                 }
966         } else {
967                 pos += scnprintf(buf + pos, bufsz - pos,
968                                  "(no data captured)\n");
969         }
970
971         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
972
973         kfree(buf);
974
975         return ret;
976 }
977 #endif
978
979 #define PRINT_MVM_REF(ref) do {                                 \
980         if (test_bit(ref, mvm->ref_bitmap))                     \
981                 pos += scnprintf(buf + pos, bufsz - pos,        \
982                                  "\t(0x%lx) %s\n",              \
983                                  BIT(ref), #ref);               \
984 } while (0)
985
986 static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
987                                         char __user *user_buf,
988                                         size_t count, loff_t *ppos)
989 {
990         struct iwl_mvm *mvm = file->private_data;
991         int pos = 0;
992         char buf[256];
993         const size_t bufsz = sizeof(buf);
994
995         pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
996                          mvm->ref_bitmap[0]);
997
998         PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
999         PRINT_MVM_REF(IWL_MVM_REF_SCAN);
1000         PRINT_MVM_REF(IWL_MVM_REF_ROC);
1001         PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
1002         PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
1003         PRINT_MVM_REF(IWL_MVM_REF_USER);
1004         PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
1005
1006         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1007 }
1008
1009 static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
1010                                          size_t count, loff_t *ppos)
1011 {
1012         unsigned long value;
1013         int ret;
1014         bool taken;
1015
1016         ret = kstrtoul(buf, 10, &value);
1017         if (ret < 0)
1018                 return ret;
1019
1020         mutex_lock(&mvm->mutex);
1021
1022         taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap);
1023         if (value == 1 && !taken)
1024                 iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
1025         else if (value == 0 && taken)
1026                 iwl_mvm_unref(mvm, IWL_MVM_REF_USER);
1027         else
1028                 ret = -EINVAL;
1029
1030         mutex_unlock(&mvm->mutex);
1031
1032         if (ret < 0)
1033                 return ret;
1034         return count;
1035 }
1036
1037 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1038         _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1039 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1040         _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1041 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {      \
1042                 if (!debugfs_create_file(alias, mode, parent, mvm,      \
1043                                          &iwl_dbgfs_##name##_ops))      \
1044                         goto err;                                       \
1045         } while (0)
1046 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
1047         MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
1048
1049 static ssize_t
1050 iwl_dbgfs_prph_reg_read(struct file *file,
1051                         char __user *user_buf,
1052                         size_t count, loff_t *ppos)
1053 {
1054         struct iwl_mvm *mvm = file->private_data;
1055         int pos = 0;
1056         char buf[32];
1057         const size_t bufsz = sizeof(buf);
1058
1059         if (!mvm->dbgfs_prph_reg_addr)
1060                 return -EINVAL;
1061
1062         pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1063                 mvm->dbgfs_prph_reg_addr,
1064                 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1065
1066         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1067 }
1068
1069 static ssize_t
1070 iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1071                          size_t count, loff_t *ppos)
1072 {
1073         u8 args;
1074         u32 value;
1075
1076         args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1077         /* if we only want to set the reg address - nothing more to do */
1078         if (args == 1)
1079                 goto out;
1080
1081         /* otherwise, make sure we have both address and value */
1082         if (args != 2)
1083                 return -EINVAL;
1084
1085         iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1086 out:
1087         return count;
1088 }
1089
1090 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
1091
1092 /* Device wide debugfs entries */
1093 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
1094 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
1095 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
1096 MVM_DEBUGFS_READ_FILE_OPS(stations);
1097 MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
1098 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
1099 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
1100 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
1101 MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
1102 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
1103 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
1104 MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
1105 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
1106 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
1107
1108 static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
1109         .open = iwl_dbgfs_fw_error_dump_open,
1110         .read = iwl_dbgfs_fw_error_dump_read,
1111         .release = iwl_dbgfs_fw_error_dump_release,
1112 };
1113
1114 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1115 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
1116 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
1117 #endif
1118
1119 #ifdef CONFIG_PM_SLEEP
1120 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
1121 #endif
1122
1123 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
1124 {
1125         struct dentry *bcast_dir __maybe_unused;
1126         char buf[100];
1127
1128         spin_lock_init(&mvm->drv_stats_lock);
1129
1130         mvm->debugfs_dir = dbgfs_dir;
1131
1132         MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR);
1133         MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
1134         MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
1135         MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
1136         MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
1137         MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
1138         MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
1139         MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
1140                              S_IRUSR | S_IWUSR);
1141         MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
1142         MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR);
1143         MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
1144         MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
1145         MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR);
1146         MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
1147                              S_IWUSR | S_IRUSR);
1148         MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
1149         MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
1150
1151 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1152         if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
1153                 bcast_dir = debugfs_create_dir("bcast_filtering",
1154                                                mvm->debugfs_dir);
1155                 if (!bcast_dir)
1156                         goto err;
1157
1158                 if (!debugfs_create_bool("override", S_IRUSR | S_IWUSR,
1159                                 bcast_dir,
1160                                 &mvm->dbgfs_bcast_filtering.override))
1161                         goto err;
1162
1163                 MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters,
1164                                            bcast_dir, S_IWUSR | S_IRUSR);
1165                 MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs,
1166                                            bcast_dir, S_IWUSR | S_IRUSR);
1167         }
1168 #endif
1169
1170 #ifdef CONFIG_PM_SLEEP
1171         MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
1172         MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);
1173         if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
1174                                  mvm->debugfs_dir, &mvm->d3_wake_sysassert))
1175                 goto err;
1176 #endif
1177
1178         if (!debugfs_create_blob("nvm_hw", S_IRUSR,
1179                                   mvm->debugfs_dir, &mvm->nvm_hw_blob))
1180                 goto err;
1181         if (!debugfs_create_blob("nvm_sw", S_IRUSR,
1182                                   mvm->debugfs_dir, &mvm->nvm_sw_blob))
1183                 goto err;
1184         if (!debugfs_create_blob("nvm_calib", S_IRUSR,
1185                                   mvm->debugfs_dir, &mvm->nvm_calib_blob))
1186                 goto err;
1187         if (!debugfs_create_blob("nvm_prod", S_IRUSR,
1188                                   mvm->debugfs_dir, &mvm->nvm_prod_blob))
1189                 goto err;
1190
1191         /*
1192          * Create a symlink with mac80211. It will be removed when mac80211
1193          * exists (before the opmode exists which removes the target.)
1194          */
1195         snprintf(buf, 100, "../../%s/%s",
1196                  dbgfs_dir->d_parent->d_parent->d_name.name,
1197                  dbgfs_dir->d_parent->d_name.name);
1198         if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf))
1199                 goto err;
1200
1201         return 0;
1202 err:
1203         IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
1204         return -ENOMEM;
1205 }