]> Git Repo - J-linux.git/blob - drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / net / wireless / intel / iwlwifi / mvm / debugfs.c
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
4  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
5  * Copyright (C) 2016-2017 Intel Deutschland GmbH
6  */
7 #include <linux/vmalloc.h>
8 #include <linux/err.h>
9 #include <linux/ieee80211.h>
10 #include <linux/netdevice.h>
11 #include <linux/dmi.h>
12
13 #include "mvm.h"
14 #include "sta.h"
15 #include "iwl-io.h"
16 #include "debugfs.h"
17 #include "iwl-modparams.h"
18 #include "iwl-drv.h"
19 #include "fw/error-dump.h"
20 #include "fw/api/phy-ctxt.h"
21
22 static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
23                                           char __user *user_buf,
24                                           size_t count, loff_t *ppos)
25 {
26         struct iwl_mvm *mvm = file->private_data;
27         char buf[16];
28         int pos, budget;
29
30         if (!iwl_mvm_is_ctdp_supported(mvm))
31                 return -EOPNOTSUPP;
32
33         if (!iwl_mvm_firmware_running(mvm) ||
34             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
35                 return -EIO;
36
37         mutex_lock(&mvm->mutex);
38         budget = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_REPORT, 0);
39         mutex_unlock(&mvm->mutex);
40
41         if (budget < 0)
42                 return budget;
43
44         pos = scnprintf(buf, sizeof(buf), "%d\n", budget);
45
46         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
47 }
48
49 static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
50                                          size_t count, loff_t *ppos)
51 {
52         int ret;
53         bool force;
54
55         if (!kstrtobool(buf, &force))
56                 IWL_DEBUG_INFO(mvm,
57                                "force start is %d [0=disabled, 1=enabled]\n",
58                                force);
59
60         /* we allow skipping cap support check and force stop ctdp
61          * statistics collection and with guerantee that it is
62          * safe to use.
63          */
64         if (!force && !iwl_mvm_is_ctdp_supported(mvm))
65                 return -EOPNOTSUPP;
66
67         if (!iwl_mvm_firmware_running(mvm) ||
68             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
69                 return -EIO;
70
71         mutex_lock(&mvm->mutex);
72         ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_STOP, 0);
73         mutex_unlock(&mvm->mutex);
74
75         return ret ?: count;
76 }
77
78 static ssize_t iwl_dbgfs_start_ctdp_write(struct iwl_mvm *mvm,
79                                           char *buf, size_t count,
80                                           loff_t *ppos)
81 {
82         int ret;
83         bool force;
84
85         if (!kstrtobool(buf, &force))
86                 IWL_DEBUG_INFO(mvm,
87                                "force start is %d [0=disabled, 1=enabled]\n",
88                                force);
89
90         /* we allow skipping cap support check and force enable ctdp
91          * for statistics collection and with guerantee that it is
92          * safe to use.
93          */
94         if (!force && !iwl_mvm_is_ctdp_supported(mvm))
95                 return -EOPNOTSUPP;
96
97         if (!iwl_mvm_firmware_running(mvm) ||
98             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
99                 return -EIO;
100
101         mutex_lock(&mvm->mutex);
102         ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START, 0);
103         mutex_unlock(&mvm->mutex);
104
105         return ret ?: count;
106 }
107
108 static ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf,
109                                             size_t count, loff_t *ppos)
110 {
111         if (!iwl_mvm_firmware_running(mvm) ||
112             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
113                 return -EIO;
114
115         iwl_mvm_enter_ctkill(mvm);
116
117         return count;
118 }
119
120 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
121                                         size_t count, loff_t *ppos)
122 {
123         int ret;
124         u32 flush_arg;
125
126         if (!iwl_mvm_firmware_running(mvm) ||
127             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
128                 return -EIO;
129
130         if (kstrtou32(buf, 0, &flush_arg))
131                 return -EINVAL;
132
133         if (iwl_mvm_has_new_tx_api(mvm)) {
134                 IWL_DEBUG_TX_QUEUES(mvm,
135                                     "FLUSHING all tids queues on sta_id = %d\n",
136                                     flush_arg);
137                 mutex_lock(&mvm->mutex);
138                 ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFFFF)
139                         ? : count;
140                 mutex_unlock(&mvm->mutex);
141                 return ret;
142         }
143
144         IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n",
145                             flush_arg);
146
147         mutex_lock(&mvm->mutex);
148         ret =  iwl_mvm_flush_tx_path(mvm, flush_arg) ? : count;
149         mutex_unlock(&mvm->mutex);
150
151         return ret;
152 }
153
154 static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
155                                          size_t count, loff_t *ppos)
156 {
157         struct iwl_mvm_sta *mvmsta;
158         int sta_id, drain, ret;
159
160         if (!iwl_mvm_firmware_running(mvm) ||
161             mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
162                 return -EIO;
163
164         if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
165                 return -EINVAL;
166         if (sta_id < 0 || sta_id >= mvm->fw->ucode_capa.num_stations)
167                 return -EINVAL;
168         if (drain < 0 || drain > 1)
169                 return -EINVAL;
170
171         mutex_lock(&mvm->mutex);
172
173         mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
174
175         if (!mvmsta)
176                 ret = -ENOENT;
177         else
178                 ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
179
180         mutex_unlock(&mvm->mutex);
181
182         return ret;
183 }
184
185 static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
186                                    size_t count, loff_t *ppos)
187 {
188         struct iwl_mvm *mvm = file->private_data;
189         const struct fw_img *img;
190         unsigned int ofs, len;
191         size_t ret;
192         u8 *ptr;
193
194         if (!iwl_mvm_firmware_running(mvm))
195                 return -EINVAL;
196
197         /* default is to dump the entire data segment */
198         img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
199         ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
200         len = img->sec[IWL_UCODE_SECTION_DATA].len;
201
202         if (mvm->dbgfs_sram_len) {
203                 ofs = mvm->dbgfs_sram_offset;
204                 len = mvm->dbgfs_sram_len;
205         }
206
207         ptr = kzalloc(len, GFP_KERNEL);
208         if (!ptr)
209                 return -ENOMEM;
210
211         iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
212
213         ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
214
215         kfree(ptr);
216
217         return ret;
218 }
219
220 static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
221                                     size_t count, loff_t *ppos)
222 {
223         const struct fw_img *img;
224         u32 offset, len;
225         u32 img_offset, img_len;
226
227         if (!iwl_mvm_firmware_running(mvm))
228                 return -EINVAL;
229
230         img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
231         img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
232         img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
233
234         if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
235                 if ((offset & 0x3) || (len & 0x3))
236                         return -EINVAL;
237
238                 if (offset + len > img_offset + img_len)
239                         return -EINVAL;
240
241                 mvm->dbgfs_sram_offset = offset;
242                 mvm->dbgfs_sram_len = len;
243         } else {
244                 mvm->dbgfs_sram_offset = 0;
245                 mvm->dbgfs_sram_len = 0;
246         }
247
248         return count;
249 }
250
251 static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
252                                                   char __user *user_buf,
253                                                   size_t count, loff_t *ppos)
254 {
255         struct iwl_mvm *mvm = file->private_data;
256         char buf[16];
257         int pos;
258
259         if (!mvm->temperature_test)
260                 pos = scnprintf(buf, sizeof(buf), "disabled\n");
261         else
262                 pos = scnprintf(buf, sizeof(buf), "%d\n", mvm->temperature);
263
264         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
265 }
266
267 /*
268  * Set NIC Temperature
269  * Cause the driver to ignore the actual NIC temperature reported by the FW
270  * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -
271  * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX
272  * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE
273  */
274 static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
275                                                    char *buf, size_t count,
276                                                    loff_t *ppos)
277 {
278         int temperature;
279
280         if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test)
281                 return -EIO;
282
283         if (kstrtoint(buf, 10, &temperature))
284                 return -EINVAL;
285         /* not a legal temperature */
286         if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX &&
287              temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) ||
288             temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN)
289                 return -EINVAL;
290
291         mutex_lock(&mvm->mutex);
292         if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) {
293                 if (!mvm->temperature_test)
294                         goto out;
295
296                 mvm->temperature_test = false;
297                 /* Since we can't read the temp while awake, just set
298                  * it to zero until we get the next RX stats from the
299                  * firmware.
300                  */
301                 mvm->temperature = 0;
302         } else {
303                 mvm->temperature_test = true;
304                 mvm->temperature = temperature;
305         }
306         IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
307                        mvm->temperature_test ? "En" : "Dis",
308                        mvm->temperature);
309         /* handle the temperature change */
310         iwl_mvm_tt_handler(mvm);
311
312 out:
313         mutex_unlock(&mvm->mutex);
314
315         return count;
316 }
317
318 static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
319                                        char __user *user_buf,
320                                        size_t count, loff_t *ppos)
321 {
322         struct iwl_mvm *mvm = file->private_data;
323         char buf[16];
324         int pos, ret;
325         s32 temp;
326
327         if (!iwl_mvm_firmware_running(mvm))
328                 return -EIO;
329
330         mutex_lock(&mvm->mutex);
331         ret = iwl_mvm_get_temp(mvm, &temp);
332         mutex_unlock(&mvm->mutex);
333
334         if (ret)
335                 return -EIO;
336
337         pos = scnprintf(buf, sizeof(buf), "%d\n", temp);
338
339         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
340 }
341
342 #ifdef CONFIG_ACPI
343 static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
344                                               char __user *user_buf,
345                                               size_t count, loff_t *ppos)
346 {
347         struct iwl_mvm *mvm = file->private_data;
348         char buf[256];
349         int pos = 0;
350         int bufsz = sizeof(buf);
351         int tbl_idx;
352
353         if (!iwl_mvm_firmware_running(mvm))
354                 return -EIO;
355
356         mutex_lock(&mvm->mutex);
357         tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
358         if (tbl_idx < 0) {
359                 mutex_unlock(&mvm->mutex);
360                 return tbl_idx;
361         }
362
363         if (!tbl_idx) {
364                 pos = scnprintf(buf, bufsz,
365                                 "SAR geographic profile disabled\n");
366         } else {
367                 pos += scnprintf(buf + pos, bufsz - pos,
368                                  "Use geographic profile %d\n", tbl_idx);
369                 pos += scnprintf(buf + pos, bufsz - pos,
370                                  "2.4GHz:\n\tChain A offset: %u dBm\n\tChain B offset: %u dBm\n\tmax tx power: %u dBm\n",
371                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[0],
372                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[1],
373                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].max);
374                 pos += scnprintf(buf + pos, bufsz - pos,
375                                  "5.2GHz:\n\tChain A offset: %u dBm\n\tChain B offset: %u dBm\n\tmax tx power: %u dBm\n",
376                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[0],
377                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[1],
378                                  mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].max);
379         }
380         mutex_unlock(&mvm->mutex);
381
382         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
383 }
384
385 static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file,
386                                              char __user *user_buf,
387                                              size_t count, loff_t *ppos)
388 {
389         struct iwl_mvm *mvm = file->private_data;
390         int err, pos;
391         char buf[12];
392         u32 value;
393
394         err = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value);
395         if (err)
396                 return err;
397
398         pos = sprintf(buf, "0x%08x\n", value);
399
400         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
401 }
402 #endif
403
404 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
405                                        size_t count, loff_t *ppos)
406 {
407         struct iwl_mvm *mvm = file->private_data;
408         struct ieee80211_sta *sta;
409         char buf[400];
410         int i, pos = 0, bufsz = sizeof(buf);
411
412         mutex_lock(&mvm->mutex);
413
414         for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
415                 pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
416                 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
417                                                 lockdep_is_held(&mvm->mutex));
418                 if (!sta)
419                         pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
420                 else if (IS_ERR(sta))
421                         pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
422                                          PTR_ERR(sta));
423                 else
424                         pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
425                                          sta->addr);
426         }
427
428         mutex_unlock(&mvm->mutex);
429
430         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
431 }
432
433 static ssize_t iwl_dbgfs_rs_data_read(struct ieee80211_link_sta *link_sta,
434                                       struct iwl_mvm_sta *mvmsta,
435                                       struct iwl_mvm *mvm,
436                                       struct iwl_mvm_link_sta *mvm_link_sta,
437                                       char __user *user_buf,
438                                       size_t count, loff_t *ppos)
439 {
440         struct iwl_lq_sta_rs_fw *lq_sta = &mvm_link_sta->lq_sta.rs_fw;
441         static const size_t bufsz = 2048;
442         char *buff;
443         int desc = 0;
444         ssize_t ret;
445
446         buff = kmalloc(bufsz, GFP_KERNEL);
447         if (!buff)
448                 return -ENOMEM;
449
450         desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n",
451                           lq_sta->pers.sta_id);
452         desc += scnprintf(buff + desc, bufsz - desc,
453                           "fixed rate 0x%X\n",
454                           lq_sta->pers.dbg_fixed_rate);
455         desc += scnprintf(buff + desc, bufsz - desc,
456                           "A-MPDU size limit %d\n",
457                           lq_sta->pers.dbg_agg_frame_count_lim);
458         desc += scnprintf(buff + desc, bufsz - desc,
459                           "valid_tx_ant %s%s\n",
460                 (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "",
461                 (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");
462         desc += scnprintf(buff + desc, bufsz - desc,
463                           "last tx rate=0x%X ",
464                           lq_sta->last_rate_n_flags);
465
466         desc += rs_pretty_print_rate(buff + desc, bufsz - desc,
467                                      lq_sta->last_rate_n_flags);
468         if (desc < bufsz - 1)
469                 buff[desc++] = '\n';
470
471         ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
472         kfree(buff);
473         return ret;
474 }
475
476 static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_link_sta *link_sta,
477                                          struct iwl_mvm_sta *mvmsta,
478                                          struct iwl_mvm *mvm,
479                                          struct iwl_mvm_link_sta *mvm_link_sta,
480                                          char *buf, size_t count,
481                                          loff_t *ppos)
482 {
483         int i;
484         u16 amsdu_len;
485
486         if (kstrtou16(buf, 0, &amsdu_len))
487                 return -EINVAL;
488
489         /* only change from debug set <-> debug unset */
490         if (amsdu_len && mvm_link_sta->orig_amsdu_len)
491                 return -EBUSY;
492
493         if (amsdu_len) {
494                 mvm_link_sta->orig_amsdu_len = link_sta->agg.max_amsdu_len;
495                 link_sta->agg.max_amsdu_len = amsdu_len;
496                 link_sta->agg.max_amsdu_len = amsdu_len;
497                 for (i = 0; i < ARRAY_SIZE(link_sta->agg.max_tid_amsdu_len); i++)
498                         link_sta->agg.max_tid_amsdu_len[i] = amsdu_len;
499         } else {
500                 link_sta->agg.max_amsdu_len = mvm_link_sta->orig_amsdu_len;
501                 mvm_link_sta->orig_amsdu_len = 0;
502         }
503
504         ieee80211_sta_recalc_aggregates(link_sta->sta);
505
506         return count;
507 }
508
509 static ssize_t iwl_dbgfs_amsdu_len_read(struct ieee80211_link_sta *link_sta,
510                                         struct iwl_mvm_sta *mvmsta,
511                                         struct iwl_mvm *mvm,
512                                         struct iwl_mvm_link_sta *mvm_link_sta,
513                                         char __user *user_buf,
514                                         size_t count, loff_t *ppos)
515 {
516         char buf[32];
517         int pos;
518
519         pos = scnprintf(buf, sizeof(buf), "current %d ",
520                         link_sta->agg.max_amsdu_len);
521         pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
522                          mvm_link_sta->orig_amsdu_len);
523
524         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
525 }
526
527 static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
528                                                 char __user *user_buf,
529                                                 size_t count, loff_t *ppos)
530 {
531         struct iwl_mvm *mvm = file->private_data;
532         char buf[64];
533         int bufsz = sizeof(buf);
534         int pos = 0;
535
536         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
537                          mvm->disable_power_off);
538         pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
539                          mvm->disable_power_off_d3);
540
541         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
542 }
543
544 static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
545                                                  size_t count, loff_t *ppos)
546 {
547         int ret, val;
548
549         if (!iwl_mvm_firmware_running(mvm))
550                 return -EIO;
551
552         if (!strncmp("disable_power_off_d0=", buf, 21)) {
553                 if (sscanf(buf + 21, "%d", &val) != 1)
554                         return -EINVAL;
555                 mvm->disable_power_off = val;
556         } else if (!strncmp("disable_power_off_d3=", buf, 21)) {
557                 if (sscanf(buf + 21, "%d", &val) != 1)
558                         return -EINVAL;
559                 mvm->disable_power_off_d3 = val;
560         } else {
561                 return -EINVAL;
562         }
563
564         mutex_lock(&mvm->mutex);
565         ret = iwl_mvm_power_update_device(mvm);
566         mutex_unlock(&mvm->mutex);
567
568         return ret ?: count;
569 }
570
571 static
572 int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
573                            int pos, int bufsz)
574 {
575         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
576
577         BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
578         BT_MBOX_PRINT(0, LE_PROF1, false);
579         BT_MBOX_PRINT(0, LE_PROF2, false);
580         BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
581         BT_MBOX_PRINT(0, CHL_SEQ_N, false);
582         BT_MBOX_PRINT(0, INBAND_S, false);
583         BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
584         BT_MBOX_PRINT(0, LE_SCAN, false);
585         BT_MBOX_PRINT(0, LE_ADV, false);
586         BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
587         BT_MBOX_PRINT(0, OPEN_CON_1, true);
588
589         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
590
591         BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
592         BT_MBOX_PRINT(1, IP_SR, false);
593         BT_MBOX_PRINT(1, LE_MSTR, false);
594         BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
595         BT_MBOX_PRINT(1, MSG_TYPE, false);
596         BT_MBOX_PRINT(1, SSN, true);
597
598         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
599
600         BT_MBOX_PRINT(2, SNIFF_ACT, false);
601         BT_MBOX_PRINT(2, PAG, false);
602         BT_MBOX_PRINT(2, INQUIRY, false);
603         BT_MBOX_PRINT(2, CONN, false);
604         BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
605         BT_MBOX_PRINT(2, DISC, false);
606         BT_MBOX_PRINT(2, SCO_TX_ACT, false);
607         BT_MBOX_PRINT(2, SCO_RX_ACT, false);
608         BT_MBOX_PRINT(2, ESCO_RE_TX, false);
609         BT_MBOX_PRINT(2, SCO_DURATION, true);
610
611         pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
612
613         BT_MBOX_PRINT(3, SCO_STATE, false);
614         BT_MBOX_PRINT(3, SNIFF_STATE, false);
615         BT_MBOX_PRINT(3, A2DP_STATE, false);
616         BT_MBOX_PRINT(3, A2DP_SRC, false);
617         BT_MBOX_PRINT(3, ACL_STATE, false);
618         BT_MBOX_PRINT(3, MSTR_STATE, false);
619         BT_MBOX_PRINT(3, OBX_STATE, false);
620         BT_MBOX_PRINT(3, OPEN_CON_2, false);
621         BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
622         BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
623         BT_MBOX_PRINT(3, INBAND_P, false);
624         BT_MBOX_PRINT(3, MSG_TYPE_2, false);
625         BT_MBOX_PRINT(3, SSN_2, false);
626         BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
627
628         return pos;
629 }
630
631 static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
632                                        size_t count, loff_t *ppos)
633 {
634         struct iwl_mvm *mvm = file->private_data;
635         struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
636         char *buf;
637         int ret, pos = 0, bufsz = sizeof(char) * 1024;
638
639         buf = kmalloc(bufsz, GFP_KERNEL);
640         if (!buf)
641                 return -ENOMEM;
642
643         mutex_lock(&mvm->mutex);
644
645         pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
646
647         pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n",
648                          notif->bt_ci_compliance);
649         pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n",
650                          le32_to_cpu(notif->primary_ch_lut));
651         pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n",
652                          le32_to_cpu(notif->secondary_ch_lut));
653         pos += scnprintf(buf + pos,
654                          bufsz - pos, "bt_activity_grading = %d\n",
655                          le32_to_cpu(notif->bt_activity_grading));
656         pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
657                          notif->rrc_status & 0xF);
658         pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
659                          notif->ttc_status & 0xF);
660
661         pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
662                          IWL_MVM_BT_COEX_SYNC2SCO);
663         pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
664                          IWL_MVM_BT_COEX_MPLUT);
665
666         mutex_unlock(&mvm->mutex);
667
668         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
669         kfree(buf);
670
671         return ret;
672 }
673 #undef BT_MBOX_PRINT
674
675 static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
676                                      size_t count, loff_t *ppos)
677 {
678         struct iwl_mvm *mvm = file->private_data;
679         struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
680         char buf[256];
681         int bufsz = sizeof(buf);
682         int pos = 0;
683
684         mutex_lock(&mvm->mutex);
685
686         pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n");
687         pos += scnprintf(buf + pos, bufsz - pos,
688                          "\tPrimary Channel Bitmap 0x%016llx\n",
689                          le64_to_cpu(cmd->bt_primary_ci));
690         pos += scnprintf(buf + pos, bufsz - pos,
691                          "\tSecondary Channel Bitmap 0x%016llx\n",
692                          le64_to_cpu(cmd->bt_secondary_ci));
693
694         mutex_unlock(&mvm->mutex);
695
696         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
697 }
698
699 static ssize_t
700 iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
701                            size_t count, loff_t *ppos)
702 {
703         u32 bt_tx_prio;
704
705         if (sscanf(buf, "%u", &bt_tx_prio) != 1)
706                 return -EINVAL;
707         if (bt_tx_prio > 4)
708                 return -EINVAL;
709
710         mvm->bt_tx_prio = bt_tx_prio;
711
712         return count;
713 }
714
715 static ssize_t
716 iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
717                              size_t count, loff_t *ppos)
718 {
719         static const char * const modes_str[BT_FORCE_ANT_MAX] = {
720                 [BT_FORCE_ANT_DIS] = "dis",
721                 [BT_FORCE_ANT_AUTO] = "auto",
722                 [BT_FORCE_ANT_BT] = "bt",
723                 [BT_FORCE_ANT_WIFI] = "wifi",
724         };
725         int ret, bt_force_ant_mode;
726
727         ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
728         if (ret < 0)
729                 return ret;
730
731         bt_force_ant_mode = ret;
732         ret = 0;
733         mutex_lock(&mvm->mutex);
734         if (mvm->bt_force_ant_mode == bt_force_ant_mode)
735                 goto out;
736
737         mvm->bt_force_ant_mode = bt_force_ant_mode;
738         IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
739                        modes_str[mvm->bt_force_ant_mode]);
740
741         if (iwl_mvm_firmware_running(mvm))
742                 ret = iwl_mvm_send_bt_init_conf(mvm);
743         else
744                 ret = 0;
745
746 out:
747         mutex_unlock(&mvm->mutex);
748         return ret ?: count;
749 }
750
751 static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
752                                      size_t count, loff_t *ppos)
753 {
754         struct iwl_mvm *mvm = file->private_data;
755         char *buff, *pos, *endpos;
756         static const size_t bufsz = 1024;
757         char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
758         int ret;
759
760         buff = kmalloc(bufsz, GFP_KERNEL);
761         if (!buff)
762                 return -ENOMEM;
763
764         pos = buff;
765         endpos = pos + bufsz;
766
767         pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
768                          iwl_drv_get_fwname_pre(mvm->trans, _fw_name_pre));
769         pos += scnprintf(pos, endpos - pos, "FW: %s\n",
770                          mvm->fwrt.fw->human_readable);
771         pos += scnprintf(pos, endpos - pos, "Device: %s\n",
772                          mvm->fwrt.trans->name);
773         pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
774                          mvm->fwrt.dev->bus->name);
775
776         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
777         kfree(buff);
778
779         return ret;
780 }
781
782 static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file,
783                                              char __user *user_buf,
784                                              size_t count, loff_t *ppos)
785 {
786         struct iwl_mvm *mvm = file->private_data;
787         struct iwl_mvm_tas_status_resp tas_rsp;
788         struct iwl_mvm_tas_status_resp *rsp = &tas_rsp;
789         static const size_t bufsz = 1024;
790         char *buff, *pos, *endpos;
791         const char * const tas_dis_reason[TAS_DISABLED_REASON_MAX] = {
792                 [TAS_DISABLED_DUE_TO_BIOS] =
793                         "Due To BIOS",
794                 [TAS_DISABLED_DUE_TO_SAR_6DBM] =
795                         "Due To SAR Limit Less Than 6 dBm",
796                 [TAS_DISABLED_REASON_INVALID] =
797                         "N/A",
798         };
799         const char * const tas_current_status[TAS_DYNA_STATUS_MAX] = {
800                 [TAS_DYNA_INACTIVE] = "INACTIVE",
801                 [TAS_DYNA_INACTIVE_MVM_MODE] =
802                         "inactive due to mvm mode",
803                 [TAS_DYNA_INACTIVE_TRIGGER_MODE] =
804                         "inactive due to trigger mode",
805                 [TAS_DYNA_INACTIVE_BLOCK_LISTED] =
806                         "inactive due to block listed",
807                 [TAS_DYNA_INACTIVE_UHB_NON_US] =
808                         "inactive due to uhb non US",
809                 [TAS_DYNA_ACTIVE] = "ACTIVE",
810         };
811         struct iwl_host_cmd hcmd = {
812                 .id = WIDE_ID(DEBUG_GROUP, GET_TAS_STATUS),
813                 .flags = CMD_WANT_SKB,
814                 .len = { 0, },
815                 .data = { NULL, },
816         };
817         int ret, i, tmp;
818         bool tas_enabled = false;
819         unsigned long dyn_status;
820
821         if (!iwl_mvm_firmware_running(mvm))
822                 return -ENODEV;
823
824         mutex_lock(&mvm->mutex);
825         ret = iwl_mvm_send_cmd(mvm, &hcmd);
826         mutex_unlock(&mvm->mutex);
827         if (ret < 0)
828                 return ret;
829
830         buff = kzalloc(bufsz, GFP_KERNEL);
831         if (!buff)
832                 return -ENOMEM;
833         pos = buff;
834         endpos = pos + bufsz;
835
836         rsp = (void *)hcmd.resp_pkt->data;
837
838         pos += scnprintf(pos, endpos - pos, "TAS Conclusion:\n");
839         for (i = 0; i < rsp->in_dual_radio + 1; i++) {
840                 if (rsp->tas_status_mac[i].band != TAS_LMAC_BAND_INVALID &&
841                     rsp->tas_status_mac[i].dynamic_status & BIT(TAS_DYNA_ACTIVE)) {
842                         pos += scnprintf(pos, endpos - pos, "\tON for ");
843                         switch (rsp->tas_status_mac[i].band) {
844                         case TAS_LMAC_BAND_HB:
845                                 pos += scnprintf(pos, endpos - pos, "HB\n");
846                                 break;
847                         case TAS_LMAC_BAND_LB:
848                                 pos += scnprintf(pos, endpos - pos, "LB\n");
849                                 break;
850                         case TAS_LMAC_BAND_UHB:
851                                 pos += scnprintf(pos, endpos - pos, "UHB\n");
852                                 break;
853                         case TAS_LMAC_BAND_INVALID:
854                                 pos += scnprintf(pos, endpos - pos,
855                                                  "INVALID BAND\n");
856                                 break;
857                         default:
858                                 pos += scnprintf(pos, endpos - pos,
859                                                  "Unsupported band (%d)\n",
860                                                  rsp->tas_status_mac[i].band);
861                                 goto out;
862                         }
863                         tas_enabled = true;
864                 }
865         }
866         if (!tas_enabled)
867                 pos += scnprintf(pos, endpos - pos, "\tOFF\n");
868
869         pos += scnprintf(pos, endpos - pos, "TAS Report\n");
870         pos += scnprintf(pos, endpos - pos, "TAS FW version: %d\n",
871                          rsp->tas_fw_version);
872         pos += scnprintf(pos, endpos - pos, "Is UHB enabled for USA?: %s\n",
873                          rsp->is_uhb_for_usa_enable ? "True" : "False");
874         pos += scnprintf(pos, endpos - pos, "Current MCC: 0x%x\n",
875                          le16_to_cpu(rsp->curr_mcc));
876
877         pos += scnprintf(pos, endpos - pos, "Block list entries:");
878         for (i = 0; i < IWL_WTAS_BLACK_LIST_MAX; i++)
879                 pos += scnprintf(pos, endpos - pos, " 0x%x",
880                                  le16_to_cpu(rsp->block_list[i]));
881
882         pos += scnprintf(pos, endpos - pos, "\nOEM name: %s\n",
883                          dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
884         pos += scnprintf(pos, endpos - pos, "\tVendor In Approved List: %s\n",
885                          iwl_is_tas_approved() ? "YES" : "NO");
886         pos += scnprintf(pos, endpos - pos,
887                          "\tDo TAS Support Dual Radio?: %s\n",
888                          rsp->in_dual_radio ? "TRUE" : "FALSE");
889
890         for (i = 0; i < rsp->in_dual_radio + 1; i++) {
891                 if (rsp->tas_status_mac[i].static_status == 0) {
892                         pos += scnprintf(pos, endpos - pos,
893                                          "Static status: disabled\n");
894                         pos += scnprintf(pos, endpos - pos,
895                                          "Static disabled reason: %s (0)\n",
896                                          tas_dis_reason[0]);
897                         goto out;
898                 }
899
900                 pos += scnprintf(pos, endpos - pos, "TAS status for ");
901                 switch (rsp->tas_status_mac[i].band) {
902                 case TAS_LMAC_BAND_HB:
903                         pos += scnprintf(pos, endpos - pos, "High band\n");
904                         break;
905                 case TAS_LMAC_BAND_LB:
906                         pos += scnprintf(pos, endpos - pos, "Low band\n");
907                         break;
908                 case TAS_LMAC_BAND_UHB:
909                         pos += scnprintf(pos, endpos - pos,
910                                          "Ultra high band\n");
911                         break;
912                 case TAS_LMAC_BAND_INVALID:
913                         pos += scnprintf(pos, endpos - pos,
914                                          "INVALID band\n");
915                         break;
916                 default:
917                         pos += scnprintf(pos, endpos - pos,
918                                          "Unsupported band (%d)\n",
919                                          rsp->tas_status_mac[i].band);
920                         goto out;
921                 }
922                 pos += scnprintf(pos, endpos - pos, "Static status: %sabled\n",
923                                  rsp->tas_status_mac[i].static_status ?
924                                  "En" : "Dis");
925                 pos += scnprintf(pos, endpos - pos,
926                                  "\tStatic Disabled Reason: ");
927                 if (rsp->tas_status_mac[i].static_dis_reason < TAS_DISABLED_REASON_MAX)
928                         pos += scnprintf(pos, endpos - pos, "%s (%d)\n",
929                                          tas_dis_reason[rsp->tas_status_mac[i].static_dis_reason],
930                                          rsp->tas_status_mac[i].static_dis_reason);
931                 else
932                         pos += scnprintf(pos, endpos - pos,
933                                          "unsupported value (%d)\n",
934                                          rsp->tas_status_mac[i].static_dis_reason);
935
936                 pos += scnprintf(pos, endpos - pos, "Dynamic status:\n");
937                 dyn_status = (rsp->tas_status_mac[i].dynamic_status);
938                 for_each_set_bit(tmp, &dyn_status, sizeof(dyn_status)) {
939                         if (tmp >= 0 && tmp < TAS_DYNA_STATUS_MAX)
940                                 pos += scnprintf(pos, endpos - pos,
941                                                  "\t%s (%d)\n",
942                                                  tas_current_status[tmp], tmp);
943                 }
944
945                 pos += scnprintf(pos, endpos - pos,
946                                  "Is near disconnection?: %s\n",
947                                  rsp->tas_status_mac[i].near_disconnection ?
948                                  "True" : "False");
949                 tmp = le16_to_cpu(rsp->tas_status_mac[i].max_reg_pwr_limit);
950                 pos += scnprintf(pos, endpos - pos,
951                                  "Max. regulatory pwr limit (dBm): %d.%03d\n",
952                                  tmp / 8, 125 * (tmp % 8));
953                 tmp = le16_to_cpu(rsp->tas_status_mac[i].sar_limit);
954                 pos += scnprintf(pos, endpos - pos,
955                                  "SAR limit (dBm): %d.%03d\n",
956                                  tmp / 8, 125 * (tmp % 8));
957         }
958
959 out:
960         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
961         kfree(buff);
962         iwl_free_resp(&hcmd);
963         return ret;
964 }
965
966 static ssize_t iwl_dbgfs_phy_integration_ver_read(struct file *file,
967                                                   char __user *user_buf,
968                                                   size_t count, loff_t *ppos)
969 {
970         struct iwl_mvm *mvm = file->private_data;
971         char *buf;
972         size_t bufsz;
973         int pos;
974         ssize_t ret;
975
976         bufsz = mvm->fw->phy_integration_ver_len + 2;
977         buf = kmalloc(bufsz, GFP_KERNEL);
978         if (!buf)
979                 return -ENOMEM;
980
981         pos = scnprintf(buf, bufsz, "%.*s\n", mvm->fw->phy_integration_ver_len,
982                         mvm->fw->phy_integration_ver);
983
984         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
985
986         kfree(buf);
987         return ret;
988 }
989
990 #define PRINT_STATS_LE32(_struct, _memb)                                \
991                          pos += scnprintf(buf + pos, bufsz - pos,       \
992                                           fmt_table, #_memb,            \
993                                           le32_to_cpu(_struct->_memb))
994
995 static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
996                                           char __user *user_buf, size_t count,
997                                           loff_t *ppos)
998 {
999         struct iwl_mvm *mvm = file->private_data;
1000         static const char *fmt_table = "\t%-30s %10u\n";
1001         static const char *fmt_header = "%-32s\n";
1002         int pos = 0;
1003         char *buf;
1004         int ret;
1005         size_t bufsz;
1006         u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
1007                                            WIDE_ID(SYSTEM_GROUP,
1008                                                    SYSTEM_STATISTICS_CMD),
1009                                            IWL_FW_CMD_VER_UNKNOWN);
1010
1011         if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
1012                 return -EOPNOTSUPP;
1013
1014         if (iwl_mvm_has_new_rx_stats_api(mvm))
1015                 bufsz = ((sizeof(struct mvm_statistics_rx) /
1016                           sizeof(__le32)) * 43) + (4 * 33) + 1;
1017         else
1018                 /* 43 = size of each data line; 33 = size of each header */
1019                 bufsz = ((sizeof(struct mvm_statistics_rx_v3) /
1020                           sizeof(__le32)) * 43) + (4 * 33) + 1;
1021
1022         buf = kzalloc(bufsz, GFP_KERNEL);
1023         if (!buf)
1024                 return -ENOMEM;
1025
1026         mutex_lock(&mvm->mutex);
1027
1028         if (iwl_mvm_firmware_running(mvm))
1029                 iwl_mvm_request_statistics(mvm, false);
1030
1031         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1032                          "Statistics_Rx - OFDM");
1033         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1034                 struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm;
1035
1036                 PRINT_STATS_LE32(ofdm, ina_cnt);
1037                 PRINT_STATS_LE32(ofdm, fina_cnt);
1038                 PRINT_STATS_LE32(ofdm, plcp_err);
1039                 PRINT_STATS_LE32(ofdm, crc32_err);
1040                 PRINT_STATS_LE32(ofdm, overrun_err);
1041                 PRINT_STATS_LE32(ofdm, early_overrun_err);
1042                 PRINT_STATS_LE32(ofdm, crc32_good);
1043                 PRINT_STATS_LE32(ofdm, false_alarm_cnt);
1044                 PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
1045                 PRINT_STATS_LE32(ofdm, sfd_timeout);
1046                 PRINT_STATS_LE32(ofdm, fina_timeout);
1047                 PRINT_STATS_LE32(ofdm, unresponded_rts);
1048                 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
1049                 PRINT_STATS_LE32(ofdm, sent_ack_cnt);
1050                 PRINT_STATS_LE32(ofdm, sent_cts_cnt);
1051                 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
1052                 PRINT_STATS_LE32(ofdm, dsp_self_kill);
1053                 PRINT_STATS_LE32(ofdm, mh_format_err);
1054                 PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
1055                 PRINT_STATS_LE32(ofdm, reserved);
1056         } else {
1057                 struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm;
1058
1059                 PRINT_STATS_LE32(ofdm, unresponded_rts);
1060                 PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
1061                 PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
1062                 PRINT_STATS_LE32(ofdm, dsp_self_kill);
1063                 PRINT_STATS_LE32(ofdm, reserved);
1064         }
1065
1066         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1067                          "Statistics_Rx - CCK");
1068         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1069                 struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck;
1070
1071                 PRINT_STATS_LE32(cck, ina_cnt);
1072                 PRINT_STATS_LE32(cck, fina_cnt);
1073                 PRINT_STATS_LE32(cck, plcp_err);
1074                 PRINT_STATS_LE32(cck, crc32_err);
1075                 PRINT_STATS_LE32(cck, overrun_err);
1076                 PRINT_STATS_LE32(cck, early_overrun_err);
1077                 PRINT_STATS_LE32(cck, crc32_good);
1078                 PRINT_STATS_LE32(cck, false_alarm_cnt);
1079                 PRINT_STATS_LE32(cck, fina_sync_err_cnt);
1080                 PRINT_STATS_LE32(cck, sfd_timeout);
1081                 PRINT_STATS_LE32(cck, fina_timeout);
1082                 PRINT_STATS_LE32(cck, unresponded_rts);
1083                 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
1084                 PRINT_STATS_LE32(cck, sent_ack_cnt);
1085                 PRINT_STATS_LE32(cck, sent_cts_cnt);
1086                 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
1087                 PRINT_STATS_LE32(cck, dsp_self_kill);
1088                 PRINT_STATS_LE32(cck, mh_format_err);
1089                 PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
1090                 PRINT_STATS_LE32(cck, reserved);
1091         } else {
1092                 struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck;
1093
1094                 PRINT_STATS_LE32(cck, unresponded_rts);
1095                 PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
1096                 PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
1097                 PRINT_STATS_LE32(cck, dsp_self_kill);
1098                 PRINT_STATS_LE32(cck, reserved);
1099         }
1100
1101         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1102                          "Statistics_Rx - GENERAL");
1103         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1104                 struct mvm_statistics_rx_non_phy_v3 *general =
1105                         &mvm->rx_stats_v3.general;
1106
1107                 PRINT_STATS_LE32(general, bogus_cts);
1108                 PRINT_STATS_LE32(general, bogus_ack);
1109                 PRINT_STATS_LE32(general, non_bssid_frames);
1110                 PRINT_STATS_LE32(general, filtered_frames);
1111                 PRINT_STATS_LE32(general, non_channel_beacons);
1112                 PRINT_STATS_LE32(general, channel_beacons);
1113                 PRINT_STATS_LE32(general, num_missed_bcon);
1114                 PRINT_STATS_LE32(general, adc_rx_saturation_time);
1115                 PRINT_STATS_LE32(general, ina_detection_search_time);
1116                 PRINT_STATS_LE32(general, beacon_silence_rssi_a);
1117                 PRINT_STATS_LE32(general, beacon_silence_rssi_b);
1118                 PRINT_STATS_LE32(general, beacon_silence_rssi_c);
1119                 PRINT_STATS_LE32(general, interference_data_flag);
1120                 PRINT_STATS_LE32(general, channel_load);
1121                 PRINT_STATS_LE32(general, dsp_false_alarms);
1122                 PRINT_STATS_LE32(general, beacon_rssi_a);
1123                 PRINT_STATS_LE32(general, beacon_rssi_b);
1124                 PRINT_STATS_LE32(general, beacon_rssi_c);
1125                 PRINT_STATS_LE32(general, beacon_energy_a);
1126                 PRINT_STATS_LE32(general, beacon_energy_b);
1127                 PRINT_STATS_LE32(general, beacon_energy_c);
1128                 PRINT_STATS_LE32(general, num_bt_kills);
1129                 PRINT_STATS_LE32(general, mac_id);
1130                 PRINT_STATS_LE32(general, directed_data_mpdu);
1131         } else {
1132                 struct mvm_statistics_rx_non_phy *general =
1133                         &mvm->rx_stats.general;
1134
1135                 PRINT_STATS_LE32(general, bogus_cts);
1136                 PRINT_STATS_LE32(general, bogus_ack);
1137                 PRINT_STATS_LE32(general, non_channel_beacons);
1138                 PRINT_STATS_LE32(general, channel_beacons);
1139                 PRINT_STATS_LE32(general, num_missed_bcon);
1140                 PRINT_STATS_LE32(general, adc_rx_saturation_time);
1141                 PRINT_STATS_LE32(general, ina_detection_search_time);
1142                 PRINT_STATS_LE32(general, beacon_silence_rssi_a);
1143                 PRINT_STATS_LE32(general, beacon_silence_rssi_b);
1144                 PRINT_STATS_LE32(general, beacon_silence_rssi_c);
1145                 PRINT_STATS_LE32(general, interference_data_flag);
1146                 PRINT_STATS_LE32(general, channel_load);
1147                 PRINT_STATS_LE32(general, beacon_rssi_a);
1148                 PRINT_STATS_LE32(general, beacon_rssi_b);
1149                 PRINT_STATS_LE32(general, beacon_rssi_c);
1150                 PRINT_STATS_LE32(general, beacon_energy_a);
1151                 PRINT_STATS_LE32(general, beacon_energy_b);
1152                 PRINT_STATS_LE32(general, beacon_energy_c);
1153                 PRINT_STATS_LE32(general, num_bt_kills);
1154                 PRINT_STATS_LE32(general, mac_id);
1155         }
1156
1157         pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1158                          "Statistics_Rx - HT");
1159         if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1160                 struct mvm_statistics_rx_ht_phy_v1 *ht =
1161                         &mvm->rx_stats_v3.ofdm_ht;
1162
1163                 PRINT_STATS_LE32(ht, plcp_err);
1164                 PRINT_STATS_LE32(ht, overrun_err);
1165                 PRINT_STATS_LE32(ht, early_overrun_err);
1166                 PRINT_STATS_LE32(ht, crc32_good);
1167                 PRINT_STATS_LE32(ht, crc32_err);
1168                 PRINT_STATS_LE32(ht, mh_format_err);
1169                 PRINT_STATS_LE32(ht, agg_crc32_good);
1170                 PRINT_STATS_LE32(ht, agg_mpdu_cnt);
1171                 PRINT_STATS_LE32(ht, agg_cnt);
1172                 PRINT_STATS_LE32(ht, unsupport_mcs);
1173         } else {
1174                 struct mvm_statistics_rx_ht_phy *ht =
1175                         &mvm->rx_stats.ofdm_ht;
1176
1177                 PRINT_STATS_LE32(ht, mh_format_err);
1178                 PRINT_STATS_LE32(ht, agg_mpdu_cnt);
1179                 PRINT_STATS_LE32(ht, agg_cnt);
1180                 PRINT_STATS_LE32(ht, unsupport_mcs);
1181         }
1182
1183         mutex_unlock(&mvm->mutex);
1184
1185         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1186         kfree(buf);
1187
1188         return ret;
1189 }
1190 #undef PRINT_STAT_LE32
1191
1192 static ssize_t iwl_dbgfs_fw_system_stats_read(struct file *file,
1193                                               char __user *user_buf,
1194                                               size_t count, loff_t *ppos)
1195 {
1196         char *buff, *pos, *endpos;
1197         int ret;
1198         size_t bufsz;
1199         int i;
1200         struct iwl_mvm_vif *mvmvif;
1201         struct ieee80211_vif *vif;
1202         struct iwl_mvm *mvm = file->private_data;
1203         u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
1204                                            WIDE_ID(SYSTEM_GROUP,
1205                                                    SYSTEM_STATISTICS_CMD),
1206                                            IWL_FW_CMD_VER_UNKNOWN);
1207
1208         /* in case of a wrong cmd version, allocate buffer only for error msg */
1209         bufsz = (cmd_ver == 1) ? 4096 : 64;
1210
1211         buff = kzalloc(bufsz, GFP_KERNEL);
1212         if (!buff)
1213                 return -ENOMEM;
1214
1215         pos = buff;
1216         endpos = pos + bufsz;
1217
1218         if (cmd_ver != 1) {
1219                 pos += scnprintf(pos, endpos - pos,
1220                                  "System stats not supported:%d\n", cmd_ver);
1221                 goto send_out;
1222         }
1223
1224         mutex_lock(&mvm->mutex);
1225         if (iwl_mvm_firmware_running(mvm))
1226                 iwl_mvm_request_statistics(mvm, false);
1227
1228         for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
1229                 vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
1230                 if (!vif)
1231                         continue;
1232
1233                 if (vif->type == NL80211_IFTYPE_STATION)
1234                         break;
1235         }
1236
1237         if (i == NUM_MAC_INDEX_DRIVER || !vif) {
1238                 pos += scnprintf(pos, endpos - pos, "vif is NULL\n");
1239                 goto release_send_out;
1240         }
1241
1242         mvmvif = iwl_mvm_vif_from_mac80211(vif);
1243         if (!mvmvif) {
1244                 pos += scnprintf(pos, endpos - pos, "mvmvif is NULL\n");
1245                 goto release_send_out;
1246         }
1247
1248         for_each_mvm_vif_valid_link(mvmvif, i) {
1249                 struct iwl_mvm_vif_link_info *link_info = mvmvif->link[i];
1250
1251                 pos += scnprintf(pos, endpos - pos,
1252                                  "link_id %d", i);
1253                 pos += scnprintf(pos, endpos - pos,
1254                                  " num_beacons %d",
1255                                  link_info->beacon_stats.num_beacons);
1256                 pos += scnprintf(pos, endpos - pos,
1257                                  " accu_num_beacons %d",
1258                                  link_info->beacon_stats.accu_num_beacons);
1259                 pos += scnprintf(pos, endpos - pos,
1260                                  " avg_signal %d\n",
1261                                  link_info->beacon_stats.avg_signal);
1262         }
1263
1264         pos += scnprintf(pos, endpos - pos,
1265                          "radio_stats.rx_time %lld\n",
1266                          mvm->radio_stats.rx_time);
1267         pos += scnprintf(pos, endpos - pos,
1268                          "radio_stats.tx_time %lld\n",
1269                          mvm->radio_stats.tx_time);
1270         pos += scnprintf(pos, endpos - pos,
1271                          "accu_radio_stats.rx_time %lld\n",
1272                          mvm->accu_radio_stats.rx_time);
1273         pos += scnprintf(pos, endpos - pos,
1274                          "accu_radio_stats.tx_time %lld\n",
1275                          mvm->accu_radio_stats.tx_time);
1276
1277 release_send_out:
1278         mutex_unlock(&mvm->mutex);
1279
1280 send_out:
1281         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
1282         kfree(buff);
1283
1284         return ret;
1285 }
1286
1287 static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
1288                                           char __user *user_buf, size_t count,
1289                                           loff_t *ppos,
1290                                           struct iwl_mvm_frame_stats *stats)
1291 {
1292         char *buff, *pos, *endpos;
1293         int idx, i;
1294         int ret;
1295         static const size_t bufsz = 1024;
1296
1297         buff = kmalloc(bufsz, GFP_KERNEL);
1298         if (!buff)
1299                 return -ENOMEM;
1300
1301         spin_lock_bh(&mvm->drv_stats_lock);
1302
1303         pos = buff;
1304         endpos = pos + bufsz;
1305
1306         pos += scnprintf(pos, endpos - pos,
1307                          "Legacy/HT/VHT\t:\t%d/%d/%d\n",
1308                          stats->legacy_frames,
1309                          stats->ht_frames,
1310                          stats->vht_frames);
1311         pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
1312                          stats->bw_20_frames,
1313                          stats->bw_40_frames,
1314                          stats->bw_80_frames);
1315         pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
1316                          stats->ngi_frames,
1317                          stats->sgi_frames);
1318         pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
1319                          stats->siso_frames,
1320                          stats->mimo2_frames);
1321         pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
1322                          stats->fail_frames,
1323                          stats->success_frames);
1324         pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
1325                          stats->agg_frames);
1326         pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
1327                          stats->ampdu_count);
1328         pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
1329                          stats->ampdu_count > 0 ?
1330                          (stats->agg_frames / stats->ampdu_count) : 0);
1331
1332         pos += scnprintf(pos, endpos - pos, "Last Rates\n");
1333
1334         idx = stats->last_frame_idx - 1;
1335         for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
1336                 idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
1337                 if (stats->last_rates[idx] == 0)
1338                         continue;
1339                 pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
1340                                  (int)(ARRAY_SIZE(stats->last_rates) - i));
1341                 pos += rs_pretty_print_rate_v1(pos, endpos - pos,
1342                                                stats->last_rates[idx]);
1343                 if (pos < endpos - 1)
1344                         *pos++ = '\n';
1345         }
1346         spin_unlock_bh(&mvm->drv_stats_lock);
1347
1348         ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
1349         kfree(buff);
1350
1351         return ret;
1352 }
1353
1354 static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
1355                                            char __user *user_buf, size_t count,
1356                                            loff_t *ppos)
1357 {
1358         struct iwl_mvm *mvm = file->private_data;
1359
1360         return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
1361                                           &mvm->drv_rx_stats);
1362 }
1363
1364 static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
1365                                           size_t count, loff_t *ppos)
1366 {
1367         int __maybe_unused ret;
1368
1369         if (!iwl_mvm_firmware_running(mvm))
1370                 return -EIO;
1371
1372         mutex_lock(&mvm->mutex);
1373
1374         /* allow one more restart that we're provoking here */
1375         if (mvm->fw_restart >= 0)
1376                 mvm->fw_restart++;
1377
1378         if (count == 6 && !strcmp(buf, "nolog\n")) {
1379                 set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
1380                 set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
1381         }
1382
1383         /* take the return value to make compiler happy - it will fail anyway */
1384         ret = iwl_mvm_send_cmd_pdu(mvm,
1385                                    WIDE_ID(LONG_GROUP, REPLY_ERROR),
1386                                    0, 0, NULL);
1387
1388         mutex_unlock(&mvm->mutex);
1389
1390         return count;
1391 }
1392
1393 static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
1394                                       size_t count, loff_t *ppos)
1395 {
1396         if (!iwl_mvm_firmware_running(mvm))
1397                 return -EIO;
1398
1399         if (count == 6 && !strcmp(buf, "nolog\n"))
1400                 set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
1401
1402         iwl_force_nmi(mvm->trans);
1403
1404         return count;
1405 }
1406
1407 static ssize_t
1408 iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
1409                                 char __user *user_buf,
1410                                 size_t count, loff_t *ppos)
1411 {
1412         struct iwl_mvm *mvm = file->private_data;
1413         int pos = 0;
1414         char buf[32];
1415         const size_t bufsz = sizeof(buf);
1416
1417         /* print which antennas were set for the scan command by the user */
1418         pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
1419         if (mvm->scan_rx_ant & ANT_A)
1420                 pos += scnprintf(buf + pos, bufsz - pos, "A");
1421         if (mvm->scan_rx_ant & ANT_B)
1422                 pos += scnprintf(buf + pos, bufsz - pos, "B");
1423         pos += scnprintf(buf + pos, bufsz - pos, " (%x)\n", mvm->scan_rx_ant);
1424
1425         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1426 }
1427
1428 static ssize_t
1429 iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
1430                                  size_t count, loff_t *ppos)
1431 {
1432         u8 scan_rx_ant;
1433
1434         if (!iwl_mvm_firmware_running(mvm))
1435                 return -EIO;
1436
1437         if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
1438                 return -EINVAL;
1439         if (scan_rx_ant > ANT_ABC)
1440                 return -EINVAL;
1441         if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
1442                 return -EINVAL;
1443
1444         if (mvm->scan_rx_ant != scan_rx_ant) {
1445                 mvm->scan_rx_ant = scan_rx_ant;
1446                 if (fw_has_capa(&mvm->fw->ucode_capa,
1447                                 IWL_UCODE_TLV_CAPA_UMAC_SCAN))
1448                         iwl_mvm_config_scan(mvm);
1449         }
1450
1451         return count;
1452 }
1453
1454 static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
1455                                                char *buf, size_t count,
1456                                                loff_t *ppos)
1457 {
1458         struct iwl_rss_config_cmd cmd = {
1459                 .flags = cpu_to_le32(IWL_RSS_ENABLE),
1460                 .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
1461                              IWL_RSS_HASH_TYPE_IPV4_UDP |
1462                              IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
1463                              IWL_RSS_HASH_TYPE_IPV6_TCP |
1464                              IWL_RSS_HASH_TYPE_IPV6_UDP |
1465                              IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
1466         };
1467         int ret, i, num_repeats, nbytes = count / 2;
1468
1469         ret = hex2bin(cmd.indirection_table, buf, nbytes);
1470         if (ret)
1471                 return ret;
1472
1473         /*
1474          * The input is the redirection table, partial or full.
1475          * Repeat the pattern if needed.
1476          * For example, input of 01020F will be repeated 42 times,
1477          * indirecting RSS hash results to queues 1, 2, 15 (skipping
1478          * queues 3 - 14).
1479          */
1480         num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
1481         for (i = 1; i < num_repeats; i++)
1482                 memcpy(&cmd.indirection_table[i * nbytes],
1483                        cmd.indirection_table, nbytes);
1484         /* handle cut in the middle pattern for the last places */
1485         memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
1486                ARRAY_SIZE(cmd.indirection_table) % nbytes);
1487
1488         netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
1489
1490         mutex_lock(&mvm->mutex);
1491         if (iwl_mvm_firmware_running(mvm))
1492                 ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
1493                                            sizeof(cmd), &cmd);
1494         else
1495                 ret = 0;
1496         mutex_unlock(&mvm->mutex);
1497
1498         return ret ?: count;
1499 }
1500
1501 static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
1502                                              char *buf, size_t count,
1503                                              loff_t *ppos)
1504 {
1505         struct iwl_op_mode *opmode = container_of((void *)mvm,
1506                                                   struct iwl_op_mode,
1507                                                   op_mode_specific);
1508         struct iwl_rx_cmd_buffer rxb = {
1509                 ._rx_page_order = 0,
1510                 .truesize = 0, /* not used */
1511                 ._offset = 0,
1512         };
1513         struct iwl_rx_packet *pkt;
1514         int bin_len = count / 2;
1515         int ret = -EINVAL;
1516
1517         if (!iwl_mvm_firmware_running(mvm))
1518                 return -EIO;
1519
1520         /* supporting only MQ RX */
1521         if (!mvm->trans->trans_cfg->mq_rx_supported)
1522                 return -EOPNOTSUPP;
1523
1524         rxb._page = alloc_pages(GFP_ATOMIC, 0);
1525         if (!rxb._page)
1526                 return -ENOMEM;
1527         pkt = rxb_addr(&rxb);
1528
1529         ret = hex2bin(page_address(rxb._page), buf, bin_len);
1530         if (ret)
1531                 goto out;
1532
1533         /* avoid invalid memory access and malformed packet */
1534         if (bin_len < sizeof(*pkt) ||
1535             bin_len != sizeof(*pkt) + iwl_rx_packet_payload_len(pkt))
1536                 goto out;
1537
1538         local_bh_disable();
1539         iwl_mvm_rx_mq(opmode, NULL, &rxb);
1540         local_bh_enable();
1541         ret = 0;
1542
1543 out:
1544         iwl_free_rxb(&rxb);
1545
1546         return ret ?: count;
1547 }
1548
1549 static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
1550 {
1551         struct ieee80211_vif *vif;
1552         struct iwl_mvm_vif *mvmvif;
1553         struct sk_buff *beacon;
1554         struct ieee80211_tx_info *info;
1555         struct iwl_mac_beacon_cmd beacon_cmd = {};
1556         unsigned int link_id;
1557         u8 rate;
1558         int i;
1559
1560         len /= 2;
1561
1562         /* Element len should be represented by u8 */
1563         if (len >= U8_MAX)
1564                 return -EINVAL;
1565
1566         if (!iwl_mvm_firmware_running(mvm))
1567                 return -EIO;
1568
1569         if (!iwl_mvm_has_new_tx_api(mvm) &&
1570             !fw_has_api(&mvm->fw->ucode_capa,
1571                         IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
1572                 return -EINVAL;
1573
1574         mutex_lock(&mvm->mutex);
1575
1576         for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
1577                 vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
1578                 if (!vif)
1579                         continue;
1580
1581                 if (vif->type == NL80211_IFTYPE_AP)
1582                         break;
1583         }
1584
1585         if (i == NUM_MAC_INDEX_DRIVER || !vif)
1586                 goto out_err;
1587
1588         mvm->hw->extra_beacon_tailroom = len;
1589
1590         beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0);
1591         if (!beacon)
1592                 goto out_err;
1593
1594         if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
1595                 dev_kfree_skb(beacon);
1596                 goto out_err;
1597         }
1598
1599         mvm->beacon_inject_active = true;
1600
1601         mvmvif = iwl_mvm_vif_from_mac80211(vif);
1602         info = IEEE80211_SKB_CB(beacon);
1603         rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
1604
1605         for_each_mvm_vif_valid_link(mvmvif, link_id) {
1606                 beacon_cmd.flags =
1607                         cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw,
1608                                                                       rate));
1609                 beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
1610                 if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
1611                         beacon_cmd.link_id =
1612                                 cpu_to_le32(mvmvif->link[link_id]->fw_link_id);
1613                 else
1614                         beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);
1615
1616                 iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
1617                                          &beacon_cmd.tim_size,
1618                                          beacon->data, beacon->len);
1619
1620                 iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
1621                                                  sizeof(beacon_cmd));
1622         }
1623         mutex_unlock(&mvm->mutex);
1624
1625         dev_kfree_skb(beacon);
1626
1627         return 0;
1628
1629 out_err:
1630         mutex_unlock(&mvm->mutex);
1631         return -EINVAL;
1632 }
1633
1634 static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
1635                                                 char *buf, size_t count,
1636                                                 loff_t *ppos)
1637 {
1638         int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
1639
1640         mvm->hw->extra_beacon_tailroom = 0;
1641         return ret ?: count;
1642 }
1643
1644 static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
1645                                                         char *buf,
1646                                                         size_t count,
1647                                                         loff_t *ppos)
1648 {
1649         int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
1650
1651         mvm->hw->extra_beacon_tailroom = 0;
1652         mvm->beacon_inject_active = false;
1653         return ret ?: count;
1654 }
1655
1656 static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
1657                                           char __user *user_buf,
1658                                           size_t count, loff_t *ppos)
1659 {
1660         struct iwl_mvm *mvm = file->private_data;
1661         int conf;
1662         char buf[8];
1663         const size_t bufsz = sizeof(buf);
1664         int pos = 0;
1665
1666         mutex_lock(&mvm->mutex);
1667         conf = mvm->fwrt.dump.conf;
1668         mutex_unlock(&mvm->mutex);
1669
1670         pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
1671
1672         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1673 }
1674
1675 static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
1676                                            char *buf, size_t count,
1677                                            loff_t *ppos)
1678 {
1679         unsigned int conf_id;
1680         int ret;
1681
1682         if (!iwl_mvm_firmware_running(mvm))
1683                 return -EIO;
1684
1685         ret = kstrtouint(buf, 0, &conf_id);
1686         if (ret)
1687                 return ret;
1688
1689         if (WARN_ON(conf_id >= FW_DBG_CONF_MAX))
1690                 return -EINVAL;
1691
1692         mutex_lock(&mvm->mutex);
1693         ret = iwl_fw_start_dbg_conf(&mvm->fwrt, conf_id);
1694         mutex_unlock(&mvm->mutex);
1695
1696         return ret ?: count;
1697 }
1698
1699 static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
1700                                               char *buf, size_t count,
1701                                               loff_t *ppos)
1702 {
1703         if (count == 0)
1704                 return 0;
1705
1706         iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER,
1707                                NULL);
1708
1709         iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
1710                            (count - 1), NULL);
1711
1712         return count;
1713 }
1714
1715 static ssize_t iwl_dbgfs_fw_dbg_clear_write(struct iwl_mvm *mvm,
1716                                             char *buf, size_t count,
1717                                             loff_t *ppos)
1718 {
1719         if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
1720                 return -EOPNOTSUPP;
1721
1722         mutex_lock(&mvm->mutex);
1723         iwl_fw_dbg_clear_monitor_buf(&mvm->fwrt);
1724         mutex_unlock(&mvm->mutex);
1725
1726         return count;
1727 }
1728
1729 static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm,
1730                                               char *buf, size_t count,
1731                                               loff_t *ppos)
1732 {
1733         u32 timepoint;
1734
1735         if (kstrtou32(buf, 0, &timepoint))
1736                 return -EINVAL;
1737
1738         if (timepoint == IWL_FW_INI_TIME_POINT_INVALID ||
1739             timepoint >= IWL_FW_INI_TIME_POINT_NUM)
1740                 return -EINVAL;
1741
1742         iwl_dbg_tlv_time_point(&mvm->fwrt, timepoint, NULL);
1743
1744         return count;
1745 }
1746
1747 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1748         _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1749 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1750         _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1751 #define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {      \
1752                 debugfs_create_file(alias, mode, parent, mvm,           \
1753                                     &iwl_dbgfs_##name##_ops);           \
1754         } while (0)
1755 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
1756         MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
1757
1758 static ssize_t
1759 _iwl_dbgfs_link_sta_wrap_write(ssize_t (*real)(struct ieee80211_link_sta *,
1760                                                struct iwl_mvm_sta *,
1761                                                struct iwl_mvm *,
1762                                                struct iwl_mvm_link_sta *,
1763                                                char *,
1764                                                size_t, loff_t *),
1765                            struct file *file,
1766                            char *buf, size_t buf_size, loff_t *ppos)
1767 {
1768         struct ieee80211_link_sta *link_sta = file->private_data;
1769         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
1770         struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
1771         struct iwl_mvm_link_sta *mvm_link_sta;
1772         ssize_t ret;
1773
1774         mutex_lock(&mvm->mutex);
1775
1776         mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
1777                                                  lockdep_is_held(&mvm->mutex));
1778         if (WARN_ON(!mvm_link_sta)) {
1779                 mutex_unlock(&mvm->mutex);
1780                 return -ENODEV;
1781         }
1782
1783         ret = real(link_sta, mvmsta, mvm, mvm_link_sta, buf, buf_size, ppos);
1784
1785         mutex_unlock(&mvm->mutex);
1786
1787         return ret;
1788 }
1789
1790 static ssize_t
1791 _iwl_dbgfs_link_sta_wrap_read(ssize_t (*real)(struct ieee80211_link_sta *,
1792                                               struct iwl_mvm_sta *,
1793                                               struct iwl_mvm *,
1794                                               struct iwl_mvm_link_sta *,
1795                                               char __user *,
1796                                               size_t, loff_t *),
1797                            struct file *file,
1798                            char __user *user_buf, size_t count, loff_t *ppos)
1799 {
1800         struct ieee80211_link_sta *link_sta = file->private_data;
1801         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
1802         struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
1803         struct iwl_mvm_link_sta *mvm_link_sta;
1804         ssize_t ret;
1805
1806         mutex_lock(&mvm->mutex);
1807
1808         mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
1809                                                  lockdep_is_held(&mvm->mutex));
1810         if (WARN_ON(!mvm_link_sta)) {
1811                 mutex_unlock(&mvm->mutex);
1812                 return -ENODEV;
1813         }
1814
1815         ret = real(link_sta, mvmsta, mvm, mvm_link_sta, user_buf, count, ppos);
1816
1817         mutex_unlock(&mvm->mutex);
1818
1819         return ret;
1820 }
1821
1822 #define MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, buflen)                \
1823 static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file,    \
1824                                          const char __user *user_buf,   \
1825                                          size_t count, loff_t *ppos)    \
1826 {                                                                       \
1827         char buf[buflen] = {};                                          \
1828         size_t buf_size = min(count, sizeof(buf) -  1);                 \
1829                                                                         \
1830         if (copy_from_user(buf, user_buf, buf_size))                    \
1831                 return -EFAULT;                                         \
1832                                                                         \
1833         return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write, \
1834                                               file,                     \
1835                                               buf, buf_size, ppos);     \
1836 }                                                                       \
1837
1838 #define MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name)         \
1839 static ssize_t _iwl_dbgfs_link_sta_##name##_read(struct file *file,     \
1840                                          char __user *user_buf,         \
1841                                          size_t count, loff_t *ppos)    \
1842 {                                                                       \
1843         return _iwl_dbgfs_link_sta_wrap_read(iwl_dbgfs_##name##_read,   \
1844                                              file,                      \
1845                                              user_buf, count, ppos);    \
1846 }                                                                       \
1847
1848 #define MVM_DEBUGFS_WRITE_LINK_STA_FILE_OPS(name, bufsz)                \
1849 MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz)                         \
1850 static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
1851         .write = _iwl_dbgfs_link_sta_##name##_write,                    \
1852         .open = simple_open,                                            \
1853         .llseek = generic_file_llseek,                                  \
1854 }
1855
1856 #define MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(name)                        \
1857 MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name)                                 \
1858 static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
1859         .read = _iwl_dbgfs_link_sta_##name##_read,                      \
1860         .open = simple_open,                                            \
1861         .llseek = generic_file_llseek,                                  \
1862 }
1863
1864 #define MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(name, bufsz)           \
1865 MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name)                                 \
1866 MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz)                         \
1867 static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
1868         .read = _iwl_dbgfs_link_sta_##name##_read,                      \
1869         .write = _iwl_dbgfs_link_sta_##name##_write,                    \
1870         .open = simple_open,                                            \
1871         .llseek = generic_file_llseek,                                  \
1872 }
1873
1874 #define MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(alias, name, parent, mode)  \
1875                 debugfs_create_file(alias, mode, parent, link_sta,      \
1876                                     &iwl_dbgfs_link_sta_##name##_ops)
1877 #define MVM_DEBUGFS_ADD_LINK_STA_FILE(name, parent, mode) \
1878         MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(#name, name, parent, mode)
1879
1880 static ssize_t
1881 iwl_dbgfs_prph_reg_read(struct file *file,
1882                         char __user *user_buf,
1883                         size_t count, loff_t *ppos)
1884 {
1885         struct iwl_mvm *mvm = file->private_data;
1886         int pos = 0;
1887         char buf[32];
1888         const size_t bufsz = sizeof(buf);
1889
1890         if (!mvm->dbgfs_prph_reg_addr)
1891                 return -EINVAL;
1892
1893         pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1894                 mvm->dbgfs_prph_reg_addr,
1895                 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1896
1897         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1898 }
1899
1900 static ssize_t
1901 iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1902                          size_t count, loff_t *ppos)
1903 {
1904         u8 args;
1905         u32 value;
1906
1907         args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1908         /* if we only want to set the reg address - nothing more to do */
1909         if (args == 1)
1910                 goto out;
1911
1912         /* otherwise, make sure we have both address and value */
1913         if (args != 2)
1914                 return -EINVAL;
1915
1916         iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1917
1918 out:
1919         return count;
1920 }
1921
1922 static ssize_t
1923 iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
1924                               size_t count, loff_t *ppos)
1925 {
1926         int ret;
1927
1928         if (!iwl_mvm_firmware_running(mvm))
1929                 return -EIO;
1930
1931         mutex_lock(&mvm->mutex);
1932         ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
1933         mutex_unlock(&mvm->mutex);
1934
1935         return ret ?: count;
1936 }
1937
1938 struct iwl_mvm_sniffer_apply {
1939         struct iwl_mvm *mvm;
1940         u8 *bssid;
1941         u16 aid;
1942 };
1943
1944 static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
1945                                   struct iwl_rx_packet *pkt, void *data)
1946 {
1947         struct iwl_mvm_sniffer_apply *apply = data;
1948
1949         apply->mvm->cur_aid = cpu_to_le16(apply->aid);
1950         memcpy(apply->mvm->cur_bssid, apply->bssid,
1951                sizeof(apply->mvm->cur_bssid));
1952
1953         return true;
1954 }
1955
1956 static ssize_t
1957 iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
1958                                   size_t count, loff_t *ppos)
1959 {
1960         struct iwl_notification_wait wait;
1961         struct iwl_he_monitor_cmd he_mon_cmd = {};
1962         struct iwl_mvm_sniffer_apply apply = {
1963                 .mvm = mvm,
1964         };
1965         u16 wait_cmds[] = {
1966                 WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
1967         };
1968         u32 aid;
1969         int ret;
1970
1971         if (!iwl_mvm_firmware_running(mvm))
1972                 return -EIO;
1973
1974         ret = sscanf(buf, "%x %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", &aid,
1975                      &he_mon_cmd.bssid[0], &he_mon_cmd.bssid[1],
1976                      &he_mon_cmd.bssid[2], &he_mon_cmd.bssid[3],
1977                      &he_mon_cmd.bssid[4], &he_mon_cmd.bssid[5]);
1978         if (ret != 7)
1979                 return -EINVAL;
1980
1981         he_mon_cmd.aid = cpu_to_le16(aid);
1982
1983         apply.aid = aid;
1984         apply.bssid = (void *)he_mon_cmd.bssid;
1985
1986         mutex_lock(&mvm->mutex);
1987
1988         /*
1989          * Use the notification waiter to get our function triggered
1990          * in sequence with other RX. This ensures that frames we get
1991          * on the RX queue _before_ the new configuration is applied
1992          * still have mvm->cur_aid pointing to the old AID, and that
1993          * frames on the RX queue _after_ the firmware processed the
1994          * new configuration (and sent the response, synchronously)
1995          * get mvm->cur_aid correctly set to the new AID.
1996          */
1997         iwl_init_notification_wait(&mvm->notif_wait, &wait,
1998                                    wait_cmds, ARRAY_SIZE(wait_cmds),
1999                                    iwl_mvm_sniffer_apply, &apply);
2000
2001         ret = iwl_mvm_send_cmd_pdu(mvm,
2002                                    WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
2003                                    0,
2004                                    sizeof(he_mon_cmd), &he_mon_cmd);
2005
2006         /* no need to really wait, we already did anyway */
2007         iwl_remove_notification(&mvm->notif_wait, &wait);
2008
2009         mutex_unlock(&mvm->mutex);
2010
2011         return ret ?: count;
2012 }
2013
2014 static ssize_t
2015 iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf,
2016                                  size_t count, loff_t *ppos)
2017 {
2018         struct iwl_mvm *mvm = file->private_data;
2019         u8 buf[32];
2020         int len;
2021
2022         len = scnprintf(buf, sizeof(buf),
2023                         "%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
2024                         le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0],
2025                         mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3],
2026                         mvm->cur_bssid[4], mvm->cur_bssid[5]);
2027
2028         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2029 }
2030
2031 static ssize_t
2032 iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
2033                                   size_t count, loff_t *ppos)
2034 {
2035         struct iwl_mvm *mvm = file->private_data;
2036         u8 buf[IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM * ETH_ALEN * 3 + 1];
2037         unsigned int pos = 0;
2038         size_t bufsz = sizeof(buf);
2039         int i;
2040
2041         mutex_lock(&mvm->mutex);
2042
2043         for (i = 0; i < IWL_MVM_UAPSD_NOAGG_LIST_LEN; i++)
2044                 pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
2045                                  mvm->uapsd_noagg_bssids[i].addr);
2046
2047         mutex_unlock(&mvm->mutex);
2048
2049         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2050 }
2051
2052 static ssize_t
2053 iwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm,
2054                            char *buf, size_t count, loff_t *ppos)
2055 {
2056         int ret;
2057         struct iwl_ltr_config_cmd ltr_config = {0};
2058
2059         if (!iwl_mvm_firmware_running(mvm))
2060                 return -EIO;
2061
2062         if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x",
2063                    &ltr_config.flags,
2064                    &ltr_config.static_long,
2065                    &ltr_config.static_short,
2066                    &ltr_config.ltr_cfg_values[0],
2067                    &ltr_config.ltr_cfg_values[1],
2068                    &ltr_config.ltr_cfg_values[2],
2069                    &ltr_config.ltr_cfg_values[3]) != 7) {
2070                 return -EINVAL;
2071         }
2072
2073         mutex_lock(&mvm->mutex);
2074         ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config),
2075                                    &ltr_config);
2076         mutex_unlock(&mvm->mutex);
2077
2078         if (ret)
2079                 IWL_ERR(mvm, "failed to send ltr configuration cmd\n");
2080
2081         return ret ?: count;
2082 }
2083
2084 static ssize_t iwl_dbgfs_rfi_freq_table_write(struct iwl_mvm *mvm, char *buf,
2085                                               size_t count, loff_t *ppos)
2086 {
2087         int ret = 0;
2088         u16 op_id;
2089
2090         if (kstrtou16(buf, 10, &op_id))
2091                 return -EINVAL;
2092
2093         /* value zero triggers re-sending the default table to the device */
2094         if (!op_id) {
2095                 mutex_lock(&mvm->mutex);
2096                 ret = iwl_rfi_send_config_cmd(mvm, NULL);
2097                 mutex_unlock(&mvm->mutex);
2098         } else {
2099                 ret = -EOPNOTSUPP; /* in the future a new table will be added */
2100         }
2101
2102         return ret ?: count;
2103 }
2104
2105 /* The size computation is as follows:
2106  * each number needs at most 3 characters, number of rows is the size of
2107  * the table; So, need 5 chars for the "freq: " part and each tuple afterwards
2108  * needs 6 characters for numbers and 5 for the punctuation around.
2109  */
2110 #define IWL_RFI_BUF_SIZE (IWL_RFI_LUT_INSTALLED_SIZE *\
2111                                 (5 + IWL_RFI_LUT_ENTRY_CHANNELS_NUM * (6 + 5)))
2112
2113 static ssize_t iwl_dbgfs_rfi_freq_table_read(struct file *file,
2114                                              char __user *user_buf,
2115                                              size_t count, loff_t *ppos)
2116 {
2117         struct iwl_mvm *mvm = file->private_data;
2118         struct iwl_rfi_freq_table_resp_cmd *resp;
2119         u32 status;
2120         char buf[IWL_RFI_BUF_SIZE];
2121         int i, j, pos = 0;
2122
2123         resp = iwl_rfi_get_freq_table(mvm);
2124         if (IS_ERR(resp))
2125                 return PTR_ERR(resp);
2126
2127         status = le32_to_cpu(resp->status);
2128         if (status != RFI_FREQ_TABLE_OK) {
2129                 scnprintf(buf, IWL_RFI_BUF_SIZE, "status = %d\n", status);
2130                 goto out;
2131         }
2132
2133         for (i = 0; i < ARRAY_SIZE(resp->table); i++) {
2134                 pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "%d: ",
2135                                  resp->table[i].freq);
2136
2137                 for (j = 0; j < ARRAY_SIZE(resp->table[i].channels); j++)
2138                         pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos,
2139                                          "(%d, %d) ",
2140                                          resp->table[i].channels[j],
2141                                          resp->table[i].bands[j]);
2142                 pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "\n");
2143         }
2144
2145 out:
2146         kfree(resp);
2147         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2148 }
2149
2150 MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
2151
2152 /* Device wide debugfs entries */
2153 MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget);
2154 MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8);
2155 MVM_DEBUGFS_WRITE_FILE_OPS(start_ctdp, 8);
2156 MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8);
2157 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
2158 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
2159 MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
2160 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
2161 MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
2162 MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
2163 MVM_DEBUGFS_READ_FILE_OPS(stations);
2164 MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(rs_data);
2165 MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
2166 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
2167 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
2168 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
2169 MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
2170 MVM_DEBUGFS_READ_FILE_OPS(fw_system_stats);
2171 MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
2172 MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver);
2173 MVM_DEBUGFS_READ_FILE_OPS(tas_get_status);
2174 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
2175 MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
2176 MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
2177 MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
2178 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
2179 MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
2180 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
2181 MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_clear, 64);
2182 MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64);
2183 MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
2184                            (IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
2185 MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
2186 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
2187 MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
2188
2189 MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
2190
2191 #ifdef CONFIG_ACPI
2192 MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
2193 MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable);
2194 #endif
2195
2196 MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(amsdu_len, 16);
2197
2198 MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
2199
2200 MVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512);
2201 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rfi_freq_table, 16);
2202
2203 static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
2204                                   size_t count, loff_t *ppos)
2205 {
2206         struct iwl_mvm *mvm = file->private_data;
2207         struct iwl_dbg_mem_access_cmd cmd = {};
2208         struct iwl_dbg_mem_access_rsp *rsp;
2209         struct iwl_host_cmd hcmd = {
2210                 .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
2211                 .data = { &cmd, },
2212                 .len = { sizeof(cmd) },
2213         };
2214         size_t delta;
2215         ssize_t ret, len;
2216
2217         if (!iwl_mvm_firmware_running(mvm))
2218                 return -EIO;
2219
2220         hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
2221         cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
2222
2223         /* Take care of alignment of both the position and the length */
2224         delta = *ppos & 0x3;
2225         cmd.addr = cpu_to_le32(*ppos - delta);
2226         cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4,
2227                                   (size_t)DEBUG_MEM_MAX_SIZE_DWORDS));
2228
2229         mutex_lock(&mvm->mutex);
2230         ret = iwl_mvm_send_cmd(mvm, &hcmd);
2231         mutex_unlock(&mvm->mutex);
2232
2233         if (ret < 0)
2234                 return ret;
2235
2236         if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
2237                 ret = -EIO;
2238                 goto out;
2239         }
2240
2241         rsp = (void *)hcmd.resp_pkt->data;
2242         if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
2243                 ret = -ENXIO;
2244                 goto out;
2245         }
2246
2247         len = min((size_t)le32_to_cpu(rsp->len) << 2,
2248                   iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
2249         len = min(len - delta, count);
2250         if (len < 0) {
2251                 ret = -EFAULT;
2252                 goto out;
2253         }
2254
2255         ret = len - copy_to_user(user_buf, (u8 *)rsp->data + delta, len);
2256         *ppos += ret;
2257
2258 out:
2259         iwl_free_resp(&hcmd);
2260         return ret;
2261 }
2262
2263 static ssize_t iwl_dbgfs_mem_write(struct file *file,
2264                                    const char __user *user_buf, size_t count,
2265                                    loff_t *ppos)
2266 {
2267         struct iwl_mvm *mvm = file->private_data;
2268         struct iwl_dbg_mem_access_cmd *cmd;
2269         struct iwl_dbg_mem_access_rsp *rsp;
2270         struct iwl_host_cmd hcmd = {};
2271         size_t cmd_size;
2272         size_t data_size;
2273         u32 op, len;
2274         ssize_t ret;
2275
2276         if (!iwl_mvm_firmware_running(mvm))
2277                 return -EIO;
2278
2279         hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
2280
2281         if (*ppos & 0x3 || count < 4) {
2282                 op = DEBUG_MEM_OP_WRITE_BYTES;
2283                 len = min(count, (size_t)(4 - (*ppos & 0x3)));
2284                 data_size = len;
2285         } else {
2286                 op = DEBUG_MEM_OP_WRITE;
2287                 len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS);
2288                 data_size = len << 2;
2289         }
2290
2291         cmd_size = sizeof(*cmd) + ALIGN(data_size, 4);
2292         cmd = kzalloc(cmd_size, GFP_KERNEL);
2293         if (!cmd)
2294                 return -ENOMEM;
2295
2296         cmd->op = cpu_to_le32(op);
2297         cmd->len = cpu_to_le32(len);
2298         cmd->addr = cpu_to_le32(*ppos);
2299         if (copy_from_user((void *)cmd->data, user_buf, data_size)) {
2300                 kfree(cmd);
2301                 return -EFAULT;
2302         }
2303
2304         hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
2305         hcmd.data[0] = (void *)cmd;
2306         hcmd.len[0] = cmd_size;
2307
2308         mutex_lock(&mvm->mutex);
2309         ret = iwl_mvm_send_cmd(mvm, &hcmd);
2310         mutex_unlock(&mvm->mutex);
2311
2312         kfree(cmd);
2313
2314         if (ret < 0)
2315                 return ret;
2316
2317         if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
2318                 ret = -EIO;
2319                 goto out;
2320         }
2321
2322         rsp = (void *)hcmd.resp_pkt->data;
2323         if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
2324                 ret = -ENXIO;
2325                 goto out;
2326         }
2327
2328         ret = data_size;
2329         *ppos += ret;
2330
2331 out:
2332         iwl_free_resp(&hcmd);
2333         return ret;
2334 }
2335
2336 static const struct file_operations iwl_dbgfs_mem_ops = {
2337         .read = iwl_dbgfs_mem_read,
2338         .write = iwl_dbgfs_mem_write,
2339         .open = simple_open,
2340         .llseek = default_llseek,
2341 };
2342
2343 void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw,
2344                                   struct ieee80211_vif *vif,
2345                                   struct ieee80211_link_sta *link_sta,
2346                                   struct dentry *dir)
2347 {
2348         struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2349
2350         if (iwl_mvm_has_tlc_offload(mvm)) {
2351                 MVM_DEBUGFS_ADD_LINK_STA_FILE(rs_data, dir, 0400);
2352         }
2353
2354         MVM_DEBUGFS_ADD_LINK_STA_FILE(amsdu_len, dir, 0600);
2355 }
2356
2357 void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
2358 {
2359         struct dentry *bcast_dir __maybe_unused;
2360
2361         spin_lock_init(&mvm->drv_stats_lock);
2362
2363         MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200);
2364         MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, 0200);
2365         MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, 0600);
2366         MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600);
2367         MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400);
2368         MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400);
2369         MVM_DEBUGFS_ADD_FILE(stop_ctdp, mvm->debugfs_dir, 0200);
2370         MVM_DEBUGFS_ADD_FILE(start_ctdp, mvm->debugfs_dir, 0200);
2371         MVM_DEBUGFS_ADD_FILE(force_ctkill, mvm->debugfs_dir, 0200);
2372         MVM_DEBUGFS_ADD_FILE(stations, mvm->debugfs_dir, 0400);
2373         MVM_DEBUGFS_ADD_FILE(bt_notif, mvm->debugfs_dir, 0400);
2374         MVM_DEBUGFS_ADD_FILE(bt_cmd, mvm->debugfs_dir, 0400);
2375         MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 0600);
2376         MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, 0400);
2377         MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400);
2378         MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400);
2379         MVM_DEBUGFS_ADD_FILE(fw_system_stats, mvm->debugfs_dir, 0400);
2380         MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200);
2381         MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200);
2382         MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, 0200);
2383         MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
2384         MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
2385         MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
2386         MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
2387         MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
2388         MVM_DEBUGFS_ADD_FILE(fw_dbg_clear, mvm->debugfs_dir, 0200);
2389         MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200);
2390         MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
2391         MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
2392         MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
2393         MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
2394         MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
2395         MVM_DEBUGFS_ADD_FILE(rfi_freq_table, mvm->debugfs_dir, 0600);
2396
2397         if (mvm->fw->phy_integration_ver)
2398                 MVM_DEBUGFS_ADD_FILE(phy_integration_ver, mvm->debugfs_dir, 0400);
2399         MVM_DEBUGFS_ADD_FILE(tas_get_status, mvm->debugfs_dir, 0400);
2400 #ifdef CONFIG_ACPI
2401         MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400);
2402         MVM_DEBUGFS_ADD_FILE(wifi_6e_enable, mvm->debugfs_dir, 0400);
2403 #endif
2404         MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
2405
2406         if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
2407                 MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200);
2408
2409         debugfs_create_bool("enable_scan_iteration_notif", 0600,
2410                             mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
2411         debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,
2412                             &mvm->drop_bcn_ap_mode);
2413
2414         MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR);
2415
2416 #ifdef CONFIG_PM_SLEEP
2417         MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
2418         debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
2419                             &mvm->d3_wake_sysassert);
2420         debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
2421                            &mvm->last_netdetect_scans);
2422 #endif
2423
2424         debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir,
2425                           &mvm->ps_disabled);
2426         debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir,
2427                             &mvm->nvm_hw_blob);
2428         debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir,
2429                             &mvm->nvm_sw_blob);
2430         debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir,
2431                             &mvm->nvm_calib_blob);
2432         debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir,
2433                             &mvm->nvm_prod_blob);
2434         debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir,
2435                             &mvm->nvm_phy_sku_blob);
2436         debugfs_create_blob("nvm_reg", S_IRUSR,
2437                             mvm->debugfs_dir, &mvm->nvm_reg_blob);
2438
2439         debugfs_create_file("mem", 0600, mvm->debugfs_dir, mvm,
2440                             &iwl_dbgfs_mem_ops);
2441
2442         /*
2443          * Create a symlink with mac80211. It will be removed when mac80211
2444          * exists (before the opmode exists which removes the target.)
2445          */
2446         if (!IS_ERR(mvm->debugfs_dir)) {
2447                 char buf[100];
2448
2449                 snprintf(buf, 100, "../../%pd2", mvm->debugfs_dir->d_parent);
2450                 debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir,
2451                                        buf);
2452         }
2453 }
This page took 0.182492 seconds and 4 git commands to generate.