]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
iwlwifi: mvm: allow to limit the A-MSDU from debugfs
[karo-tx-linux.git] / drivers / net / wireless / intel / 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  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
10  * Copyright(c) 2016 Intel Deutschland GmbH
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of version 2 of the GNU General Public License as
14  * published by the Free Software Foundation.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
24  * USA
25  *
26  * The full GNU General Public License is included in this distribution
27  * in the file called COPYING.
28  *
29  * Contact Information:
30  *  Intel Linux Wireless <linuxwifi@intel.com>
31  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
32  *
33  * BSD LICENSE
34  *
35  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
36  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  *
43  *  * Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  *  * Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in
47  *    the documentation and/or other materials provided with the
48  *    distribution.
49  *  * Neither the name Intel Corporation nor the names of its
50  *    contributors may be used to endorse or promote products derived
51  *    from this software without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
56  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
57  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
59  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
63  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  *
65  *****************************************************************************/
66 #include <linux/vmalloc.h>
67 #include <linux/ieee80211.h>
68
69 #include "mvm.h"
70 #include "fw-dbg.h"
71 #include "sta.h"
72 #include "iwl-io.h"
73 #include "debugfs.h"
74 #include "iwl-fw-error-dump.h"
75
76 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
77                                         size_t count, loff_t *ppos)
78 {
79         int ret;
80         u32 scd_q_msk;
81
82         if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
83                 return -EIO;
84
85         if (sscanf(buf, "%x", &scd_q_msk) != 1)
86                 return -EINVAL;
87
88         IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
89
90         mutex_lock(&mvm->mutex);
91         ret =  iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count;
92         mutex_unlock(&mvm->mutex);
93
94         return ret;
95 }
96
97 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
98                                          size_t count, loff_t *ppos)
99 {
100         struct iwl_mvm_sta *mvmsta;
101         int sta_id, drain, ret;
102
103         if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
104                 return -EIO;
105
106         if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
107                 return -EINVAL;
108         if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
109                 return -EINVAL;
110         if (drain < 0 || drain > 1)
111                 return -EINVAL;
112
113         mutex_lock(&mvm->mutex);
114
115         mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
116
117         if (!mvmsta)
118                 ret = -ENOENT;
119         else
120                 ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
121
122         mutex_unlock(&mvm->mutex);
123
124         return ret;
125 }
126
127 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
128                                    size_t count, loff_t *ppos)
129 {
130         struct iwl_mvm *mvm = file->private_data;
131         const struct fw_img *img;
132         unsigned int ofs, len;
133         size_t ret;
134         u8 *ptr;
135
136         if (!mvm->ucode_loaded)
137                 return -EINVAL;
138
139         /* default is to dump the entire data segment */
140         img = &mvm->fw->img[mvm->cur_ucode];
141         ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
142         len = img->sec[IWL_UCODE_SECTION_DATA].len;
143
144         if (mvm->dbgfs_sram_len) {
145                 ofs = mvm->dbgfs_sram_offset;
146                 len = mvm->dbgfs_sram_len;
147         }
148
149         ptr = kzalloc(len, GFP_KERNEL);
150         if (!ptr)
151                 return -ENOMEM;
152
153         iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
154
155         ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
156
157         kfree(ptr);
158
159         return ret;
160 }
161
162 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
163                                     size_t count, loff_t *ppos)
164 {
165         const struct fw_img *img;
166         u32 offset, len;
167         u32 img_offset, img_len;
168
169         if (!mvm->ucode_loaded)
170                 return -EINVAL;
171
172         img = &mvm->fw->img[mvm->cur_ucode];
173         img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
174         img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
175
176         if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
177                 if ((offset & 0x3) || (len & 0x3))
178                         return -EINVAL;
179
180                 if (offset + len > img_offset + img_len)
181                         return -EINVAL;
182
183                 mvm->dbgfs_sram_offset = offset;
184                 mvm->dbgfs_sram_len = len;
185         } else {
186                 mvm->dbgfs_sram_offset = 0;
187                 mvm->dbgfs_sram_len = 0;
188         }
189
190         return count;
191 }
192
193 static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
194                                                   char __user *user_buf,
195                                                   size_t count, loff_t *ppos)
196 {
197         struct iwl_mvm *mvm = file->private_data;
198         char buf[16];
199         int pos;
200
201         if (!mvm->temperature_test)
202                 pos = scnprintf(buf , sizeof(buf), "disabled\n");
203         else
204                 pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature);
205
206         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
207 }
208
209 /*
210  * Set NIC Temperature
211  * Cause the driver to ignore the actual NIC temperature reported by the FW
212  * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -
213  * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX
214  * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE
215  */
216 static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
217                                                    char *buf, size_t count,
218                                                    loff_t *ppos)
219 {
220         int temperature;
221
222         if (!mvm->ucode_loaded && !mvm->temperature_test)
223                 return -EIO;
224
225         if (kstrtoint(buf, 10, &temperature))
226                 return -EINVAL;
227         /* not a legal temperature */
228         if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX &&
229              temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) ||
230             temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN)
231                 return -EINVAL;
232
233         mutex_lock(&mvm->mutex);
234         if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) {
235                 if (!mvm->temperature_test)
236                         goto out;
237
238                 mvm->temperature_test = false;
239                 /* Since we can't read the temp while awake, just set
240                  * it to zero until we get the next RX stats from the
241                  * firmware.
242                  */
243                 mvm->temperature = 0;
244         } else {
245                 mvm->temperature_test = true;
246                 mvm->temperature = temperature;
247         }
248         IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
249                        mvm->temperature_test ? "En" : "Dis" ,
250                        mvm->temperature);
251         /* handle the temperature change */
252         iwl_mvm_tt_handler(mvm);
253
254 out:
255         mutex_unlock(&mvm->mutex);
256
257         return count;
258 }
259
260 static ssize_t iwl_dbgfs_nic_temp_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[16];
266         int pos, ret;
267         s32 temp;
268
269         if (!mvm->ucode_loaded)
270                 return -EIO;
271
272         mutex_lock(&mvm->mutex);
273         ret = iwl_mvm_get_temp(mvm, &temp);
274         mutex_unlock(&mvm->mutex);
275
276         if (ret)
277                 return -EIO;
278
279         pos = scnprintf(buf , sizeof(buf), "%d\n", temp);
280
281         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
282 }
283
284 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
285                                        size_t count, loff_t *ppos)
286 {
287         struct iwl_mvm *mvm = file->private_data;
288         struct ieee80211_sta *sta;
289         char buf[400];
290         int i, pos = 0, bufsz = sizeof(buf);
291
292         mutex_lock(&mvm->mutex);
293
294         for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
295                 pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
296                 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
297                                                 lockdep_is_held(&mvm->mutex));
298                 if (!sta)
299                         pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
300                 else if (IS_ERR(sta))
301                         pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
302                                          PTR_ERR(sta));
303                 else
304                         pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
305                                          sta->addr);
306         }
307
308         mutex_unlock(&mvm->mutex);
309
310         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
311 }
312
313 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
314                                                 char __user *user_buf,
315                                                 size_t count, loff_t *ppos)
316 {
317         struct iwl_mvm *mvm = file->private_data;
318         char buf[64];
319         int bufsz = sizeof(buf);
320         int pos = 0;
321
322         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
323                          mvm->disable_power_off);
324         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
325                          mvm->disable_power_off_d3);
326
327         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
328 }
329
330 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
331                                                  size_t count, loff_t *ppos)
332 {
333         int ret, val;
334
335         if (!mvm->ucode_loaded)
336                 return -EIO;
337
338         if (!strncmp("disable_power_off_d0=", buf, 21)) {
339                 if (sscanf(buf + 21, "%d", &val) != 1)
340                         return -EINVAL;
341                 mvm->disable_power_off = val;
342         } else if (!strncmp("disable_power_off_d3=", buf, 21)) {
343                 if (sscanf(buf + 21, "%d", &val) != 1)
344                         return -EINVAL;
345                 mvm->disable_power_off_d3 = val;
346         } else {
347                 return -EINVAL;
348         }
349
350         mutex_lock(&mvm->mutex);
351         ret = iwl_mvm_power_update_device(mvm);
352         mutex_unlock(&mvm->mutex);
353
354         return ret ?: count;
355 }
356
357 #define BT_MBOX_MSG(_notif, _num, _field)                                    \
358         ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
359         >> BT_MBOX##_num##_##_field##_POS)
360
361
362 #define BT_MBOX_PRINT(_num, _field, _end)                                   \
363                         pos += scnprintf(buf + pos, bufsz - pos,            \
364                                          "\t%s: %d%s",                      \
365                                          #_field,                           \
366                                          BT_MBOX_MSG(notif, _num, _field),  \
367                                          true ? "\n" : ", ");
368
369 static
370 int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
371                            int pos, int bufsz)
372 {
373         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
374
375         BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
376         BT_MBOX_PRINT(0, LE_PROF1, false);
377         BT_MBOX_PRINT(0, LE_PROF2, false);
378         BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
379         BT_MBOX_PRINT(0, CHL_SEQ_N, false);
380         BT_MBOX_PRINT(0, INBAND_S, false);
381         BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
382         BT_MBOX_PRINT(0, LE_SCAN, false);
383         BT_MBOX_PRINT(0, LE_ADV, false);
384         BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
385         BT_MBOX_PRINT(0, OPEN_CON_1, true);
386
387         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
388
389         BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
390         BT_MBOX_PRINT(1, IP_SR, false);
391         BT_MBOX_PRINT(1, LE_MSTR, false);
392         BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
393         BT_MBOX_PRINT(1, MSG_TYPE, false);
394         BT_MBOX_PRINT(1, SSN, true);
395
396         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
397
398         BT_MBOX_PRINT(2, SNIFF_ACT, false);
399         BT_MBOX_PRINT(2, PAG, false);
400         BT_MBOX_PRINT(2, INQUIRY, false);
401         BT_MBOX_PRINT(2, CONN, false);
402         BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
403         BT_MBOX_PRINT(2, DISC, false);
404         BT_MBOX_PRINT(2, SCO_TX_ACT, false);
405         BT_MBOX_PRINT(2, SCO_RX_ACT, false);
406         BT_MBOX_PRINT(2, ESCO_RE_TX, false);
407         BT_MBOX_PRINT(2, SCO_DURATION, true);
408
409         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
410
411         BT_MBOX_PRINT(3, SCO_STATE, false);
412         BT_MBOX_PRINT(3, SNIFF_STATE, false);
413         BT_MBOX_PRINT(3, A2DP_STATE, false);
414         BT_MBOX_PRINT(3, ACL_STATE, false);
415         BT_MBOX_PRINT(3, MSTR_STATE, false);
416         BT_MBOX_PRINT(3, OBX_STATE, false);
417         BT_MBOX_PRINT(3, OPEN_CON_2, false);
418         BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
419         BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
420         BT_MBOX_PRINT(3, INBAND_P, false);
421         BT_MBOX_PRINT(3, MSG_TYPE_2, false);
422         BT_MBOX_PRINT(3, SSN_2, false);
423         BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
424
425         return pos;
426 }
427
428 static
429 int iwl_mvm_coex_dump_mbox_old(struct iwl_bt_coex_profile_notif_old *notif,
430                                char *buf, int pos, int bufsz)
431 {
432         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
433
434         BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
435         BT_MBOX_PRINT(0, LE_PROF1, false);
436         BT_MBOX_PRINT(0, LE_PROF2, false);
437         BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
438         BT_MBOX_PRINT(0, CHL_SEQ_N, false);
439         BT_MBOX_PRINT(0, INBAND_S, false);
440         BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
441         BT_MBOX_PRINT(0, LE_SCAN, false);
442         BT_MBOX_PRINT(0, LE_ADV, false);
443         BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
444         BT_MBOX_PRINT(0, OPEN_CON_1, true);
445
446         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
447
448         BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
449         BT_MBOX_PRINT(1, IP_SR, false);
450         BT_MBOX_PRINT(1, LE_MSTR, false);
451         BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
452         BT_MBOX_PRINT(1, MSG_TYPE, false);
453         BT_MBOX_PRINT(1, SSN, true);
454
455         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
456
457         BT_MBOX_PRINT(2, SNIFF_ACT, false);
458         BT_MBOX_PRINT(2, PAG, false);
459         BT_MBOX_PRINT(2, INQUIRY, false);
460         BT_MBOX_PRINT(2, CONN, false);
461         BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
462         BT_MBOX_PRINT(2, DISC, false);
463         BT_MBOX_PRINT(2, SCO_TX_ACT, false);
464         BT_MBOX_PRINT(2, SCO_RX_ACT, false);
465         BT_MBOX_PRINT(2, ESCO_RE_TX, false);
466         BT_MBOX_PRINT(2, SCO_DURATION, true);
467
468         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
469
470         BT_MBOX_PRINT(3, SCO_STATE, false);
471         BT_MBOX_PRINT(3, SNIFF_STATE, false);
472         BT_MBOX_PRINT(3, A2DP_STATE, false);
473         BT_MBOX_PRINT(3, ACL_STATE, false);
474         BT_MBOX_PRINT(3, MSTR_STATE, false);
475         BT_MBOX_PRINT(3, OBX_STATE, false);
476         BT_MBOX_PRINT(3, OPEN_CON_2, false);
477         BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
478         BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
479         BT_MBOX_PRINT(3, INBAND_P, false);
480         BT_MBOX_PRINT(3, MSG_TYPE_2, false);
481         BT_MBOX_PRINT(3, SSN_2, false);
482         BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
483
484         return pos;
485 }
486
487 static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
488                                        size_t count, loff_t *ppos)
489 {
490         struct iwl_mvm *mvm = file->private_data;
491         char *buf;
492         int ret, pos = 0, bufsz = sizeof(char) * 1024;
493
494         buf = kmalloc(bufsz, GFP_KERNEL);
495         if (!buf)
496                 return -ENOMEM;
497
498         mutex_lock(&mvm->mutex);
499
500         if (!fw_has_api(&mvm->fw->ucode_capa,
501                         IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
502                 struct iwl_bt_coex_profile_notif_old *notif =
503                         &mvm->last_bt_notif_old;
504
505                 pos += iwl_mvm_coex_dump_mbox_old(notif, buf, pos, bufsz);
506
507                 pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
508                                  notif->bt_ci_compliance);
509                 pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
510                                  le32_to_cpu(notif->primary_ch_lut));
511                 pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
512                                  le32_to_cpu(notif->secondary_ch_lut));
513                 pos += scnprintf(buf+pos,
514                                  bufsz-pos, "bt_activity_grading = %d\n",
515                                  le32_to_cpu(notif->bt_activity_grading));
516                 pos += scnprintf(buf+pos, bufsz-pos,
517                                  "antenna isolation = %d CORUN LUT index = %d\n",
518                                  mvm->last_ant_isol, mvm->last_corun_lut);
519                 pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
520                                  notif->rrc_enabled);
521                 pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
522                                  notif->ttc_enabled);
523         } else {
524                 struct iwl_bt_coex_profile_notif *notif =
525                         &mvm->last_bt_notif;
526
527                 pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
528
529                 pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
530                                  notif->bt_ci_compliance);
531                 pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
532                                  le32_to_cpu(notif->primary_ch_lut));
533                 pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
534                                  le32_to_cpu(notif->secondary_ch_lut));
535                 pos += scnprintf(buf+pos,
536                                  bufsz-pos, "bt_activity_grading = %d\n",
537                                  le32_to_cpu(notif->bt_activity_grading));
538                 pos += scnprintf(buf+pos, bufsz-pos,
539                                  "antenna isolation = %d CORUN LUT index = %d\n",
540                                  mvm->last_ant_isol, mvm->last_corun_lut);
541                 pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
542                                  (notif->ttc_rrc_status >> 4) & 0xF);
543                 pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
544                                  notif->ttc_rrc_status & 0xF);
545         }
546
547         pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
548                          IWL_MVM_BT_COEX_SYNC2SCO);
549         pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
550                          IWL_MVM_BT_COEX_MPLUT);
551         pos += scnprintf(buf + pos, bufsz - pos, "corunning = %d\n",
552                          IWL_MVM_BT_COEX_CORUNNING);
553
554         mutex_unlock(&mvm->mutex);
555
556         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
557         kfree(buf);
558
559         return ret;
560 }
561 #undef BT_MBOX_PRINT
562
563 static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
564                                      size_t count, loff_t *ppos)
565 {
566         struct iwl_mvm *mvm = file->private_data;
567         char buf[256];
568         int bufsz = sizeof(buf);
569         int pos = 0;
570
571         mutex_lock(&mvm->mutex);
572
573         if (!fw_has_api(&mvm->fw->ucode_capa,
574                         IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
575                 struct iwl_bt_coex_ci_cmd_old *cmd = &mvm->last_bt_ci_cmd_old;
576
577                 pos += scnprintf(buf+pos, bufsz-pos,
578                                  "Channel inhibition CMD\n");
579                 pos += scnprintf(buf+pos, bufsz-pos,
580                                "\tPrimary Channel Bitmap 0x%016llx\n",
581                                le64_to_cpu(cmd->bt_primary_ci));
582                 pos += scnprintf(buf+pos, bufsz-pos,
583                                "\tSecondary Channel Bitmap 0x%016llx\n",
584                                le64_to_cpu(cmd->bt_secondary_ci));
585
586                 pos += scnprintf(buf+pos, bufsz-pos,
587                                  "BT Configuration CMD - 0=default, 1=never, 2=always\n");
588                 pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill msk idx %d\n",
589                                  mvm->bt_ack_kill_msk[0]);
590                 pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill msk idx %d\n",
591                                  mvm->bt_cts_kill_msk[0]);
592
593         } else {
594                 struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
595
596                 pos += scnprintf(buf+pos, bufsz-pos,
597                                  "Channel inhibition CMD\n");
598                 pos += scnprintf(buf+pos, bufsz-pos,
599                                "\tPrimary Channel Bitmap 0x%016llx\n",
600                                le64_to_cpu(cmd->bt_primary_ci));
601                 pos += scnprintf(buf+pos, bufsz-pos,
602                                "\tSecondary Channel Bitmap 0x%016llx\n",
603                                le64_to_cpu(cmd->bt_secondary_ci));
604         }
605
606         mutex_unlock(&mvm->mutex);
607
608         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
609 }
610
611 static ssize_t
612 iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
613                            size_t count, loff_t *ppos)
614 {
615         u32 bt_tx_prio;
616
617         if (sscanf(buf, "%u", &bt_tx_prio) != 1)
618                 return -EINVAL;
619         if (bt_tx_prio > 4)
620                 return -EINVAL;
621
622         mvm->bt_tx_prio = bt_tx_prio;
623
624         return count;
625 }
626
627 static ssize_t
628 iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
629                              size_t count, loff_t *ppos)
630 {
631         static const char * const modes_str[BT_FORCE_ANT_MAX] = {
632                 [BT_FORCE_ANT_DIS] = "dis",
633                 [BT_FORCE_ANT_AUTO] = "auto",
634                 [BT_FORCE_ANT_BT] = "bt",
635                 [BT_FORCE_ANT_WIFI] = "wifi",
636         };
637         int ret, bt_force_ant_mode;
638
639         for (bt_force_ant_mode = 0;
640              bt_force_ant_mode < ARRAY_SIZE(modes_str);
641              bt_force_ant_mode++) {
642                 if (!strcmp(buf, modes_str[bt_force_ant_mode]))
643                         break;
644         }
645
646         if (bt_force_ant_mode >= ARRAY_SIZE(modes_str))
647                 return -EINVAL;
648
649         ret = 0;
650         mutex_lock(&mvm->mutex);
651         if (mvm->bt_force_ant_mode == bt_force_ant_mode)
652                 goto out;
653
654         mvm->bt_force_ant_mode = bt_force_ant_mode;
655         IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
656                        modes_str[mvm->bt_force_ant_mode]);
657         ret = iwl_send_bt_init_conf(mvm);
658
659 out:
660         mutex_unlock(&mvm->mutex);
661         return ret ?: count;
662 }
663
664 #define PRINT_STATS_LE32(_struct, _memb)                                \
665                          pos += scnprintf(buf + pos, bufsz - pos,       \
666                                           fmt_table, #_memb,            \
667                                           le32_to_cpu(_struct->_memb))
668
669 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
670                                           char __user *user_buf, size_t count,
671                                           loff_t *ppos)
672 {
673         struct iwl_mvm *mvm = file->private_data;
674         static const char *fmt_table = "\t%-30s %10u\n";
675         static const char *fmt_header = "%-32s\n";
676         int pos = 0;
677         char *buf;
678         int ret;
679         /* 43 is the size of each data line, 33 is the size of each header */
680         size_t bufsz =
681                 ((sizeof(struct mvm_statistics_rx) / sizeof(__le32)) * 43) +
682                 (4 * 33) + 1;
683
684         struct mvm_statistics_rx_phy *ofdm;
685         struct mvm_statistics_rx_phy *cck;
686         struct mvm_statistics_rx_non_phy *general;
687         struct mvm_statistics_rx_ht_phy *ht;
688
689         buf = kzalloc(bufsz, GFP_KERNEL);
690         if (!buf)
691                 return -ENOMEM;
692
693         mutex_lock(&mvm->mutex);
694
695         ofdm = &mvm->rx_stats.ofdm;
696         cck = &mvm->rx_stats.cck;
697         general = &mvm->rx_stats.general;
698         ht = &mvm->rx_stats.ofdm_ht;
699
700         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
701                          "Statistics_Rx - OFDM");
702         PRINT_STATS_LE32(ofdm, ina_cnt);
703         PRINT_STATS_LE32(ofdm, fina_cnt);
704         PRINT_STATS_LE32(ofdm, plcp_err);
705         PRINT_STATS_LE32(ofdm, crc32_err);
706         PRINT_STATS_LE32(ofdm, overrun_err);
707         PRINT_STATS_LE32(ofdm, early_overrun_err);
708         PRINT_STATS_LE32(ofdm, crc32_good);
709         PRINT_STATS_LE32(ofdm, false_alarm_cnt);
710         PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
711         PRINT_STATS_LE32(ofdm, sfd_timeout);
712         PRINT_STATS_LE32(ofdm, fina_timeout);
713         PRINT_STATS_LE32(ofdm, unresponded_rts);
714         PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
715         PRINT_STATS_LE32(ofdm, sent_ack_cnt);
716         PRINT_STATS_LE32(ofdm, sent_cts_cnt);
717         PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
718         PRINT_STATS_LE32(ofdm, dsp_self_kill);
719         PRINT_STATS_LE32(ofdm, mh_format_err);
720         PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
721         PRINT_STATS_LE32(ofdm, reserved);
722
723         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
724                          "Statistics_Rx - CCK");
725         PRINT_STATS_LE32(cck, ina_cnt);
726         PRINT_STATS_LE32(cck, fina_cnt);
727         PRINT_STATS_LE32(cck, plcp_err);
728         PRINT_STATS_LE32(cck, crc32_err);
729         PRINT_STATS_LE32(cck, overrun_err);
730         PRINT_STATS_LE32(cck, early_overrun_err);
731         PRINT_STATS_LE32(cck, crc32_good);
732         PRINT_STATS_LE32(cck, false_alarm_cnt);
733         PRINT_STATS_LE32(cck, fina_sync_err_cnt);
734         PRINT_STATS_LE32(cck, sfd_timeout);
735         PRINT_STATS_LE32(cck, fina_timeout);
736         PRINT_STATS_LE32(cck, unresponded_rts);
737         PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
738         PRINT_STATS_LE32(cck, sent_ack_cnt);
739         PRINT_STATS_LE32(cck, sent_cts_cnt);
740         PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
741         PRINT_STATS_LE32(cck, dsp_self_kill);
742         PRINT_STATS_LE32(cck, mh_format_err);
743         PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
744         PRINT_STATS_LE32(cck, reserved);
745
746         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
747                          "Statistics_Rx - GENERAL");
748         PRINT_STATS_LE32(general, bogus_cts);
749         PRINT_STATS_LE32(general, bogus_ack);
750         PRINT_STATS_LE32(general, non_bssid_frames);
751         PRINT_STATS_LE32(general, filtered_frames);
752         PRINT_STATS_LE32(general, non_channel_beacons);
753         PRINT_STATS_LE32(general, channel_beacons);
754         PRINT_STATS_LE32(general, num_missed_bcon);
755         PRINT_STATS_LE32(general, adc_rx_saturation_time);
756         PRINT_STATS_LE32(general, ina_detection_search_time);
757         PRINT_STATS_LE32(general, beacon_silence_rssi_a);
758         PRINT_STATS_LE32(general, beacon_silence_rssi_b);
759         PRINT_STATS_LE32(general, beacon_silence_rssi_c);
760         PRINT_STATS_LE32(general, interference_data_flag);
761         PRINT_STATS_LE32(general, channel_load);
762         PRINT_STATS_LE32(general, dsp_false_alarms);
763         PRINT_STATS_LE32(general, beacon_rssi_a);
764         PRINT_STATS_LE32(general, beacon_rssi_b);
765         PRINT_STATS_LE32(general, beacon_rssi_c);
766         PRINT_STATS_LE32(general, beacon_energy_a);
767         PRINT_STATS_LE32(general, beacon_energy_b);
768         PRINT_STATS_LE32(general, beacon_energy_c);
769         PRINT_STATS_LE32(general, num_bt_kills);
770         PRINT_STATS_LE32(general, mac_id);
771         PRINT_STATS_LE32(general, directed_data_mpdu);
772
773         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
774                          "Statistics_Rx - HT");
775         PRINT_STATS_LE32(ht, plcp_err);
776         PRINT_STATS_LE32(ht, overrun_err);
777         PRINT_STATS_LE32(ht, early_overrun_err);
778         PRINT_STATS_LE32(ht, crc32_good);
779         PRINT_STATS_LE32(ht, crc32_err);
780         PRINT_STATS_LE32(ht, mh_format_err);
781         PRINT_STATS_LE32(ht, agg_crc32_good);
782         PRINT_STATS_LE32(ht, agg_mpdu_cnt);
783         PRINT_STATS_LE32(ht, agg_cnt);
784         PRINT_STATS_LE32(ht, unsupport_mcs);
785
786         mutex_unlock(&mvm->mutex);
787
788         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
789         kfree(buf);
790
791         return ret;
792 }
793 #undef PRINT_STAT_LE32
794
795 static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
796                                           char __user *user_buf, size_t count,
797                                           loff_t *ppos,
798                                           struct iwl_mvm_frame_stats *stats)
799 {
800         char *buff, *pos, *endpos;
801         int idx, i;
802         int ret;
803         static const size_t bufsz = 1024;
804
805         buff = kmalloc(bufsz, GFP_KERNEL);
806         if (!buff)
807                 return -ENOMEM;
808
809         spin_lock_bh(&mvm->drv_stats_lock);
810
811         pos = buff;
812         endpos = pos + bufsz;
813
814         pos += scnprintf(pos, endpos - pos,
815                          "Legacy/HT/VHT\t:\t%d/%d/%d\n",
816                          stats->legacy_frames,
817                          stats->ht_frames,
818                          stats->vht_frames);
819         pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
820                          stats->bw_20_frames,
821                          stats->bw_40_frames,
822                          stats->bw_80_frames);
823         pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
824                          stats->ngi_frames,
825                          stats->sgi_frames);
826         pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
827                          stats->siso_frames,
828                          stats->mimo2_frames);
829         pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
830                          stats->fail_frames,
831                          stats->success_frames);
832         pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
833                          stats->agg_frames);
834         pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
835                          stats->ampdu_count);
836         pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
837                          stats->ampdu_count > 0 ?
838                          (stats->agg_frames / stats->ampdu_count) : 0);
839
840         pos += scnprintf(pos, endpos - pos, "Last Rates\n");
841
842         idx = stats->last_frame_idx - 1;
843         for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
844                 idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
845                 if (stats->last_rates[idx] == 0)
846                         continue;
847                 pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
848                                  (int)(ARRAY_SIZE(stats->last_rates) - i));
849                 pos += rs_pretty_print_rate(pos, stats->last_rates[idx]);
850         }
851         spin_unlock_bh(&mvm->drv_stats_lock);
852
853         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
854         kfree(buff);
855
856         return ret;
857 }
858
859 static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
860                                            char __user *user_buf, size_t count,
861                                            loff_t *ppos)
862 {
863         struct iwl_mvm *mvm = file->private_data;
864
865         return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
866                                           &mvm->drv_rx_stats);
867 }
868
869 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
870                                           size_t count, loff_t *ppos)
871 {
872         int ret;
873
874         mutex_lock(&mvm->mutex);
875
876         /* allow one more restart that we're provoking here */
877         if (mvm->restart_fw >= 0)
878                 mvm->restart_fw++;
879
880         /* take the return value to make compiler happy - it will fail anyway */
881         ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, 0, 0, NULL);
882
883         mutex_unlock(&mvm->mutex);
884
885         return count;
886 }
887
888 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
889                                       size_t count, loff_t *ppos)
890 {
891         int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
892         if (ret)
893                 return ret;
894
895         iwl_force_nmi(mvm->trans);
896
897         iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
898
899         return count;
900 }
901
902 static ssize_t
903 iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
904                                 char __user *user_buf,
905                                 size_t count, loff_t *ppos)
906 {
907         struct iwl_mvm *mvm = file->private_data;
908         int pos = 0;
909         char buf[32];
910         const size_t bufsz = sizeof(buf);
911
912         /* print which antennas were set for the scan command by the user */
913         pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
914         if (mvm->scan_rx_ant & ANT_A)
915                 pos += scnprintf(buf + pos, bufsz - pos, "A");
916         if (mvm->scan_rx_ant & ANT_B)
917                 pos += scnprintf(buf + pos, bufsz - pos, "B");
918         if (mvm->scan_rx_ant & ANT_C)
919                 pos += scnprintf(buf + pos, bufsz - pos, "C");
920         pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
921
922         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
923 }
924
925 static ssize_t
926 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
927                                  size_t count, loff_t *ppos)
928 {
929         u8 scan_rx_ant;
930
931         if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
932                 return -EINVAL;
933         if (scan_rx_ant > ANT_ABC)
934                 return -EINVAL;
935         if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
936                 return -EINVAL;
937
938         if (mvm->scan_rx_ant != scan_rx_ant) {
939                 mvm->scan_rx_ant = scan_rx_ant;
940                 if (fw_has_capa(&mvm->fw->ucode_capa,
941                                 IWL_UCODE_TLV_CAPA_UMAC_SCAN))
942                         iwl_mvm_config_scan(mvm);
943         }
944
945         return count;
946 }
947
948 static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
949                                                char *buf, size_t count,
950                                                loff_t *ppos)
951 {
952         struct iwl_rss_config_cmd cmd = {
953                 .flags = cpu_to_le32(IWL_RSS_ENABLE),
954                 .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
955                              IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
956                              IWL_RSS_HASH_TYPE_IPV6_TCP |
957                              IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
958         };
959         int ret, i, num_repeats, nbytes = count / 2;
960
961         ret = hex2bin(cmd.indirection_table, buf, nbytes);
962         if (ret)
963                 return ret;
964
965         /*
966          * The input is the redirection table, partial or full.
967          * Repeat the pattern if needed.
968          * For example, input of 01020F will be repeated 42 times,
969          * indirecting RSS hash results to queues 1, 2, 15 (skipping
970          * queues 3 - 14).
971          */
972         num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
973         for (i = 1; i < num_repeats; i++)
974                 memcpy(&cmd.indirection_table[i * nbytes],
975                        cmd.indirection_table, nbytes);
976         /* handle cut in the middle pattern for the last places */
977         memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
978                ARRAY_SIZE(cmd.indirection_table) % nbytes);
979
980         memcpy(cmd.secret_key, mvm->secret_key, sizeof(cmd.secret_key));
981
982         mutex_lock(&mvm->mutex);
983         ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
984         mutex_unlock(&mvm->mutex);
985
986         return ret ?: count;
987 }
988
989 static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
990                                           char __user *user_buf,
991                                           size_t count, loff_t *ppos)
992 {
993         struct iwl_mvm *mvm = file->private_data;
994         int conf;
995         char buf[8];
996         const size_t bufsz = sizeof(buf);
997         int pos = 0;
998
999         mutex_lock(&mvm->mutex);
1000         conf = mvm->fw_dbg_conf;
1001         mutex_unlock(&mvm->mutex);
1002
1003         pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
1004
1005         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1006 }
1007
1008 /*
1009  * Enable / Disable continuous recording.
1010  * Cause the FW to start continuous recording, by sending the relevant hcmd.
1011  * Enable: input of every integer larger than 0, ENABLE_CONT_RECORDING.
1012  * Disable: for 0 as input, DISABLE_CONT_RECORDING.
1013  */
1014 static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm,
1015                                               char *buf, size_t count,
1016                                               loff_t *ppos)
1017 {
1018         struct iwl_trans *trans = mvm->trans;
1019         const struct iwl_fw_dbg_dest_tlv *dest = trans->dbg_dest_tlv;
1020         struct iwl_continuous_record_cmd cont_rec = {};
1021         int ret, rec_mode;
1022
1023         if (!dest)
1024                 return -EOPNOTSUPP;
1025
1026         if (dest->monitor_mode != SMEM_MODE ||
1027             trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
1028                 return -EOPNOTSUPP;
1029
1030         ret = kstrtoint(buf, 0, &rec_mode);
1031         if (ret)
1032                 return ret;
1033
1034         cont_rec.record_mode.enable_recording = rec_mode ?
1035                 cpu_to_le16(ENABLE_CONT_RECORDING) :
1036                 cpu_to_le16(DISABLE_CONT_RECORDING);
1037
1038         mutex_lock(&mvm->mutex);
1039         ret = iwl_mvm_send_cmd_pdu(mvm, LDBG_CONFIG_CMD, 0,
1040                                    sizeof(cont_rec), &cont_rec);
1041         mutex_unlock(&mvm->mutex);
1042
1043         return ret ?: count;
1044 }
1045
1046 static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
1047                                            char *buf, size_t count,
1048                                            loff_t *ppos)
1049 {
1050         unsigned int conf_id;
1051         int ret;
1052
1053         ret = kstrtouint(buf, 0, &conf_id);
1054         if (ret)
1055                 return ret;
1056
1057         if (WARN_ON(conf_id >= FW_DBG_CONF_MAX))
1058                 return -EINVAL;
1059
1060         mutex_lock(&mvm->mutex);
1061         ret = iwl_mvm_start_fw_dbg_conf(mvm, conf_id);
1062         mutex_unlock(&mvm->mutex);
1063
1064         return ret ?: count;
1065 }
1066
1067 static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
1068                                               char *buf, size_t count,
1069                                               loff_t *ppos)
1070 {
1071         int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
1072
1073         if (ret)
1074                 return ret;
1075
1076         iwl_mvm_fw_dbg_collect(mvm, FW_DBG_TRIGGER_USER, buf,
1077                                (count - 1), NULL);
1078
1079         iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
1080
1081         return count;
1082 }
1083
1084 static ssize_t iwl_dbgfs_max_amsdu_len_write(struct iwl_mvm *mvm,
1085                                              char *buf, size_t count,
1086                                              loff_t *ppos)
1087 {
1088         unsigned int max_amsdu_len;
1089         int ret;
1090
1091         ret = kstrtouint(buf, 0, &max_amsdu_len);
1092
1093         if (max_amsdu_len > IEEE80211_MAX_MPDU_LEN_VHT_11454)
1094                 return -EINVAL;
1095         mvm->max_amsdu_len = max_amsdu_len;
1096
1097         return count;
1098 }
1099
1100 #define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
1101 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1102 static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
1103                                             char __user *user_buf,
1104                                             size_t count, loff_t *ppos)
1105 {
1106         struct iwl_mvm *mvm = file->private_data;
1107         struct iwl_bcast_filter_cmd cmd;
1108         const struct iwl_fw_bcast_filter *filter;
1109         char *buf;
1110         int bufsz = 1024;
1111         int i, j, pos = 0;
1112         ssize_t ret;
1113
1114         buf = kzalloc(bufsz, GFP_KERNEL);
1115         if (!buf)
1116                 return -ENOMEM;
1117
1118         mutex_lock(&mvm->mutex);
1119         if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
1120                 ADD_TEXT("None\n");
1121                 mutex_unlock(&mvm->mutex);
1122                 goto out;
1123         }
1124         mutex_unlock(&mvm->mutex);
1125
1126         for (i = 0; cmd.filters[i].attrs[0].mask; i++) {
1127                 filter = &cmd.filters[i];
1128
1129                 ADD_TEXT("Filter [%d]:\n", i);
1130                 ADD_TEXT("\tDiscard=%d\n", filter->discard);
1131                 ADD_TEXT("\tFrame Type: %s\n",
1132                          filter->frame_type ? "IPv4" : "Generic");
1133
1134                 for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) {
1135                         const struct iwl_fw_bcast_filter_attr *attr;
1136
1137                         attr = &filter->attrs[j];
1138                         if (!attr->mask)
1139                                 break;
1140
1141                         ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n",
1142                                  j, attr->offset,
1143                                  attr->offset_type ? "IP End" :
1144                                                      "Payload Start",
1145                                  be32_to_cpu(attr->mask),
1146                                  be32_to_cpu(attr->val),
1147                                  le16_to_cpu(attr->reserved1));
1148                 }
1149         }
1150 out:
1151         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1152         kfree(buf);
1153         return ret;
1154 }
1155
1156 static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
1157                                              size_t count, loff_t *ppos)
1158 {
1159         int pos, next_pos;
1160         struct iwl_fw_bcast_filter filter = {};
1161         struct iwl_bcast_filter_cmd cmd;
1162         u32 filter_id, attr_id, mask, value;
1163         int err = 0;
1164
1165         if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard,
1166                    &filter.frame_type, &pos) != 3)
1167                 return -EINVAL;
1168
1169         if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) ||
1170             filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4)
1171                 return -EINVAL;
1172
1173         for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs);
1174              attr_id++) {
1175                 struct iwl_fw_bcast_filter_attr *attr =
1176                                 &filter.attrs[attr_id];
1177
1178                 if (pos >= count)
1179                         break;
1180
1181                 if (sscanf(&buf[pos], "%hhi %hhi %i %i %n",
1182                            &attr->offset, &attr->offset_type,
1183                            &mask, &value, &next_pos) != 4)
1184                         return -EINVAL;
1185
1186                 attr->mask = cpu_to_be32(mask);
1187                 attr->val = cpu_to_be32(value);
1188                 if (mask)
1189                         filter.num_attrs++;
1190
1191                 pos += next_pos;
1192         }
1193
1194         mutex_lock(&mvm->mutex);
1195         memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id],
1196                &filter, sizeof(filter));
1197
1198         /* send updated bcast filtering configuration */
1199         if (mvm->dbgfs_bcast_filtering.override &&
1200             iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
1201                 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
1202                                            sizeof(cmd), &cmd);
1203         mutex_unlock(&mvm->mutex);
1204
1205         return err ?: count;
1206 }
1207
1208 static ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file,
1209                                                  char __user *user_buf,
1210                                                  size_t count, loff_t *ppos)
1211 {
1212         struct iwl_mvm *mvm = file->private_data;
1213         struct iwl_bcast_filter_cmd cmd;
1214         char *buf;
1215         int bufsz = 1024;
1216         int i, pos = 0;
1217         ssize_t ret;
1218
1219         buf = kzalloc(bufsz, GFP_KERNEL);
1220         if (!buf)
1221                 return -ENOMEM;
1222
1223         mutex_lock(&mvm->mutex);
1224         if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
1225                 ADD_TEXT("None\n");
1226                 mutex_unlock(&mvm->mutex);
1227                 goto out;
1228         }
1229         mutex_unlock(&mvm->mutex);
1230
1231         for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) {
1232                 const struct iwl_fw_bcast_mac *mac = &cmd.macs[i];
1233
1234                 ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n",
1235                          i, mac->default_discard, mac->attached_filters);
1236         }
1237 out:
1238         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1239         kfree(buf);
1240         return ret;
1241 }
1242
1243 static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
1244                                                   char *buf, size_t count,
1245                                                   loff_t *ppos)
1246 {
1247         struct iwl_bcast_filter_cmd cmd;
1248         struct iwl_fw_bcast_mac mac = {};
1249         u32 mac_id, attached_filters;
1250         int err = 0;
1251
1252         if (!mvm->bcast_filters)
1253                 return -ENOENT;
1254
1255         if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard,
1256                    &attached_filters) != 3)
1257                 return -EINVAL;
1258
1259         if (mac_id >= ARRAY_SIZE(cmd.macs) ||
1260             mac.default_discard > 1 ||
1261             attached_filters >= BIT(ARRAY_SIZE(cmd.filters)))
1262                 return -EINVAL;
1263
1264         mac.attached_filters = cpu_to_le16(attached_filters);
1265
1266         mutex_lock(&mvm->mutex);
1267         memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id],
1268                &mac, sizeof(mac));
1269
1270         /* send updated bcast filtering configuration */
1271         if (mvm->dbgfs_bcast_filtering.override &&
1272             iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
1273                 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
1274                                            sizeof(cmd), &cmd);
1275         mutex_unlock(&mvm->mutex);
1276
1277         return err ?: count;
1278 }
1279 #endif
1280
1281 #ifdef CONFIG_PM_SLEEP
1282 static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
1283                                        size_t count, loff_t *ppos)
1284 {
1285         int store;
1286
1287         if (sscanf(buf, "%d", &store) != 1)
1288                 return -EINVAL;
1289
1290         mvm->store_d3_resume_sram = store;
1291
1292         return count;
1293 }
1294
1295 static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
1296                                       size_t count, loff_t *ppos)
1297 {
1298         struct iwl_mvm *mvm = file->private_data;
1299         const struct fw_img *img;
1300         int ofs, len, pos = 0;
1301         size_t bufsz, ret;
1302         char *buf;
1303         u8 *ptr = mvm->d3_resume_sram;
1304
1305         img = &mvm->fw->img[IWL_UCODE_WOWLAN];
1306         len = img->sec[IWL_UCODE_SECTION_DATA].len;
1307
1308         bufsz = len * 4 + 256;
1309         buf = kzalloc(bufsz, GFP_KERNEL);
1310         if (!buf)
1311                 return -ENOMEM;
1312
1313         pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n",
1314                          mvm->store_d3_resume_sram ? "en" : "dis");
1315
1316         if (ptr) {
1317                 for (ofs = 0; ofs < len; ofs += 16) {
1318                         pos += scnprintf(buf + pos, bufsz - pos,
1319                                          "0x%.4x %16ph\n", ofs, ptr + ofs);
1320                 }
1321         } else {
1322                 pos += scnprintf(buf + pos, bufsz - pos,
1323                                  "(no data captured)\n");
1324         }
1325
1326         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1327
1328         kfree(buf);
1329
1330         return ret;
1331 }
1332 #endif
1333
1334 #define PRINT_MVM_REF(ref) do {                                         \
1335         if (mvm->refs[ref])                                             \
1336                 pos += scnprintf(buf + pos, bufsz - pos,                \
1337                                  "\t(0x%lx): %d %s\n",                  \
1338                                  BIT(ref), mvm->refs[ref], #ref);       \
1339 } while (0)
1340
1341 static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
1342                                         char __user *user_buf,
1343                                         size_t count, loff_t *ppos)
1344 {
1345         struct iwl_mvm *mvm = file->private_data;
1346         int i, pos = 0;
1347         char buf[256];
1348         const size_t bufsz = sizeof(buf);
1349         u32 refs = 0;
1350
1351         for (i = 0; i < IWL_MVM_REF_COUNT; i++)
1352                 if (mvm->refs[i])
1353                         refs |= BIT(i);
1354
1355         pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
1356                          refs);
1357
1358         PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
1359         PRINT_MVM_REF(IWL_MVM_REF_SCAN);
1360         PRINT_MVM_REF(IWL_MVM_REF_ROC);
1361         PRINT_MVM_REF(IWL_MVM_REF_ROC_AUX);
1362         PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
1363         PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
1364         PRINT_MVM_REF(IWL_MVM_REF_USER);
1365         PRINT_MVM_REF(IWL_MVM_REF_TX);
1366         PRINT_MVM_REF(IWL_MVM_REF_TX_AGG);
1367         PRINT_MVM_REF(IWL_MVM_REF_ADD_IF);
1368         PRINT_MVM_REF(IWL_MVM_REF_START_AP);
1369         PRINT_MVM_REF(IWL_MVM_REF_BSS_CHANGED);
1370         PRINT_MVM_REF(IWL_MVM_REF_PREPARE_TX);
1371         PRINT_MVM_REF(IWL_MVM_REF_PROTECT_TDLS);
1372         PRINT_MVM_REF(IWL_MVM_REF_CHECK_CTKILL);
1373         PRINT_MVM_REF(IWL_MVM_REF_PRPH_READ);
1374         PRINT_MVM_REF(IWL_MVM_REF_PRPH_WRITE);
1375         PRINT_MVM_REF(IWL_MVM_REF_NMI);
1376         PRINT_MVM_REF(IWL_MVM_REF_TM_CMD);
1377         PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
1378         PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
1379         PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT);
1380         PRINT_MVM_REF(IWL_MVM_REF_INIT_UCODE);
1381
1382         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1383 }
1384
1385 static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
1386                                          size_t count, loff_t *ppos)
1387 {
1388         unsigned long value;
1389         int ret;
1390         bool taken;
1391
1392         ret = kstrtoul(buf, 10, &value);
1393         if (ret < 0)
1394                 return ret;
1395
1396         mutex_lock(&mvm->mutex);
1397
1398         taken = mvm->refs[IWL_MVM_REF_USER];
1399         if (value == 1 && !taken)
1400                 iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
1401         else if (value == 0 && taken)
1402                 iwl_mvm_unref(mvm, IWL_MVM_REF_USER);
1403         else
1404                 ret = -EINVAL;
1405
1406         mutex_unlock(&mvm->mutex);
1407
1408         if (ret < 0)
1409                 return ret;
1410         return count;
1411 }
1412
1413 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1414         _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1415 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1416         _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1417 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {      \
1418                 if (!debugfs_create_file(alias, mode, parent, mvm,      \
1419                                          &iwl_dbgfs_##name##_ops))      \
1420                         goto err;                                       \
1421         } while (0)
1422 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
1423         MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
1424
1425 static ssize_t
1426 iwl_dbgfs_prph_reg_read(struct file *file,
1427                         char __user *user_buf,
1428                         size_t count, loff_t *ppos)
1429 {
1430         struct iwl_mvm *mvm = file->private_data;
1431         int pos = 0;
1432         char buf[32];
1433         const size_t bufsz = sizeof(buf);
1434         int ret;
1435
1436         if (!mvm->dbgfs_prph_reg_addr)
1437                 return -EINVAL;
1438
1439         ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
1440         if (ret)
1441                 return ret;
1442
1443         pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1444                 mvm->dbgfs_prph_reg_addr,
1445                 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1446
1447         iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
1448
1449         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1450 }
1451
1452 static ssize_t
1453 iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1454                          size_t count, loff_t *ppos)
1455 {
1456         u8 args;
1457         u32 value;
1458         int ret;
1459
1460         args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1461         /* if we only want to set the reg address - nothing more to do */
1462         if (args == 1)
1463                 goto out;
1464
1465         /* otherwise, make sure we have both address and value */
1466         if (args != 2)
1467                 return -EINVAL;
1468
1469         ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
1470         if (ret)
1471                 return ret;
1472
1473         iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1474
1475         iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
1476 out:
1477         return count;
1478 }
1479
1480 static ssize_t
1481 iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
1482                               size_t count, loff_t *ppos)
1483 {
1484         int ret;
1485
1486         mutex_lock(&mvm->mutex);
1487         ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
1488         mutex_unlock(&mvm->mutex);
1489
1490         return ret ?: count;
1491 }
1492
1493 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
1494
1495 /* Device wide debugfs entries */
1496 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
1497 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
1498 MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
1499 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
1500 MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
1501 MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
1502 MVM_DEBUGFS_READ_FILE_OPS(stations);
1503 MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
1504 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
1505 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
1506 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
1507 MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
1508 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
1509 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
1510 MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
1511 MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
1512 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
1513 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
1514 MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
1515 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
1516 MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8);
1517 MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
1518 MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
1519                            (IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
1520
1521 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1522 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
1523 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
1524 #endif
1525
1526 #ifdef CONFIG_PM_SLEEP
1527 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
1528 #endif
1529
1530 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
1531 {
1532         struct dentry *bcast_dir __maybe_unused;
1533         char buf[100];
1534
1535         spin_lock_init(&mvm->drv_stats_lock);
1536
1537         mvm->debugfs_dir = dbgfs_dir;
1538
1539         MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR);
1540         MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
1541         MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
1542         MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir,
1543                              S_IWUSR | S_IRUSR);
1544         MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR);
1545         MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
1546         MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
1547         MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
1548         MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
1549                              S_IRUSR | S_IWUSR);
1550         MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
1551         MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR);
1552         MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
1553         MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
1554         MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR);
1555         MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, S_IWUSR);
1556         MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
1557                              S_IWUSR | S_IRUSR);
1558         MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
1559         MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
1560         MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
1561         MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
1562         MVM_DEBUGFS_ADD_FILE(max_amsdu_len, mvm->debugfs_dir, S_IWUSR);
1563         MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR);
1564         MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR);
1565         MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR);
1566         if (!debugfs_create_bool("enable_scan_iteration_notif",
1567                                  S_IRUSR | S_IWUSR,
1568                                  mvm->debugfs_dir,
1569                                  &mvm->scan_iter_notif_enabled))
1570                 goto err;
1571         if (!debugfs_create_bool("drop_bcn_ap_mode", S_IRUSR | S_IWUSR,
1572                                  mvm->debugfs_dir, &mvm->drop_bcn_ap_mode))
1573                 goto err;
1574
1575 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1576         if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
1577                 bcast_dir = debugfs_create_dir("bcast_filtering",
1578                                                mvm->debugfs_dir);
1579                 if (!bcast_dir)
1580                         goto err;
1581
1582                 if (!debugfs_create_bool("override", S_IRUSR | S_IWUSR,
1583                                 bcast_dir,
1584                                 &mvm->dbgfs_bcast_filtering.override))
1585                         goto err;
1586
1587                 MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters,
1588                                            bcast_dir, S_IWUSR | S_IRUSR);
1589                 MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs,
1590                                            bcast_dir, S_IWUSR | S_IRUSR);
1591         }
1592 #endif
1593
1594 #ifdef CONFIG_PM_SLEEP
1595         MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
1596         MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);
1597         if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
1598                                  mvm->debugfs_dir, &mvm->d3_wake_sysassert))
1599                 goto err;
1600         if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR,
1601                                 mvm->debugfs_dir, &mvm->last_netdetect_scans))
1602                 goto err;
1603 #endif
1604
1605         if (!debugfs_create_u8("ps_disabled", S_IRUSR,
1606                                mvm->debugfs_dir, &mvm->ps_disabled))
1607                 goto err;
1608         if (!debugfs_create_blob("nvm_hw", S_IRUSR,
1609                                   mvm->debugfs_dir, &mvm->nvm_hw_blob))
1610                 goto err;
1611         if (!debugfs_create_blob("nvm_sw", S_IRUSR,
1612                                   mvm->debugfs_dir, &mvm->nvm_sw_blob))
1613                 goto err;
1614         if (!debugfs_create_blob("nvm_calib", S_IRUSR,
1615                                   mvm->debugfs_dir, &mvm->nvm_calib_blob))
1616                 goto err;
1617         if (!debugfs_create_blob("nvm_prod", S_IRUSR,
1618                                   mvm->debugfs_dir, &mvm->nvm_prod_blob))
1619                 goto err;
1620         if (!debugfs_create_blob("nvm_phy_sku", S_IRUSR,
1621                                  mvm->debugfs_dir, &mvm->nvm_phy_sku_blob))
1622                 goto err;
1623
1624         /*
1625          * Create a symlink with mac80211. It will be removed when mac80211
1626          * exists (before the opmode exists which removes the target.)
1627          */
1628         snprintf(buf, 100, "../../%s/%s",
1629                  dbgfs_dir->d_parent->d_parent->d_name.name,
1630                  dbgfs_dir->d_parent->d_name.name);
1631         if (!debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf))
1632                 goto err;
1633
1634         return 0;
1635 err:
1636         IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
1637         return -ENOMEM;
1638 }