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