cfg80211: remove enum ieee80211_band
[cascardo/linux.git] / drivers / net / wireless / intel / iwlwifi / mvm / debugfs-vif.c
1 /******************************************************************************
2  *
3  * This file is provided under a dual BSD/GPLv2 license.  When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * GPL LICENSE SUMMARY
7  *
8  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
10  * Copyright(c) 2016        Intel Deutschland GmbH
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of version 2 of the GNU General Public License as
14  * published by the Free Software Foundation.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
24  * USA
25  *
26  * The full GNU General Public License is included in this distribution
27  * in the file called COPYING.
28  *
29  * Contact Information:
30  *  Intel Linux Wireless <linuxwifi@intel.com>
31  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
32  *
33  * BSD LICENSE
34  *
35  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
36  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
37  * Copyright(c) 2016        Intel Deutschland GmbH
38  * All rights reserved.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  *
44  *  * Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  *  * Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in
48  *    the documentation and/or other materials provided with the
49  *    distribution.
50  *  * Neither the name Intel Corporation nor the names of its
51  *    contributors may be used to endorse or promote products derived
52  *    from this software without specific prior written permission.
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
55  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
56  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
57  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
58  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
59  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
60  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
61  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
62  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
63  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
64  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65  *
66  *****************************************************************************/
67 #include "mvm.h"
68 #include "fw-api-tof.h"
69 #include "debugfs.h"
70
71 static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
72                                  struct ieee80211_vif *vif,
73                                  enum iwl_dbgfs_pm_mask param, int val)
74 {
75         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
76         struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
77
78         dbgfs_pm->mask |= param;
79
80         switch (param) {
81         case MVM_DEBUGFS_PM_KEEP_ALIVE: {
82                 int dtimper = vif->bss_conf.dtim_period ?: 1;
83                 int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
84
85                 IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
86                 if (val * MSEC_PER_SEC < 3 * dtimper_msec)
87                         IWL_WARN(mvm,
88                                  "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
89                                  val * MSEC_PER_SEC, 3 * dtimper_msec);
90                 dbgfs_pm->keep_alive_seconds = val;
91                 break;
92         }
93         case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
94                 IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
95                                 val ? "enabled" : "disabled");
96                 dbgfs_pm->skip_over_dtim = val;
97                 break;
98         case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
99                 IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
100                 dbgfs_pm->skip_dtim_periods = val;
101                 break;
102         case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
103                 IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
104                 dbgfs_pm->rx_data_timeout = val;
105                 break;
106         case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
107                 IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
108                 dbgfs_pm->tx_data_timeout = val;
109                 break;
110         case MVM_DEBUGFS_PM_LPRX_ENA:
111                 IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
112                 dbgfs_pm->lprx_ena = val;
113                 break;
114         case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
115                 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
116                 dbgfs_pm->lprx_rssi_threshold = val;
117                 break;
118         case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
119                 IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
120                 dbgfs_pm->snooze_ena = val;
121                 break;
122         case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING:
123                 IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val);
124                 dbgfs_pm->uapsd_misbehaving = val;
125                 break;
126         case MVM_DEBUGFS_PM_USE_PS_POLL:
127                 IWL_DEBUG_POWER(mvm, "use_ps_poll=%d\n", val);
128                 dbgfs_pm->use_ps_poll = val;
129                 break;
130         }
131 }
132
133 static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
134                                          size_t count, loff_t *ppos)
135 {
136         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
137         struct iwl_mvm *mvm = mvmvif->mvm;
138         enum iwl_dbgfs_pm_mask param;
139         int val, ret;
140
141         if (!strncmp("keep_alive=", buf, 11)) {
142                 if (sscanf(buf + 11, "%d", &val) != 1)
143                         return -EINVAL;
144                 param = MVM_DEBUGFS_PM_KEEP_ALIVE;
145         } else if (!strncmp("skip_over_dtim=", buf, 15)) {
146                 if (sscanf(buf + 15, "%d", &val) != 1)
147                         return -EINVAL;
148                 param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
149         } else if (!strncmp("skip_dtim_periods=", buf, 18)) {
150                 if (sscanf(buf + 18, "%d", &val) != 1)
151                         return -EINVAL;
152                 param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
153         } else if (!strncmp("rx_data_timeout=", buf, 16)) {
154                 if (sscanf(buf + 16, "%d", &val) != 1)
155                         return -EINVAL;
156                 param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
157         } else if (!strncmp("tx_data_timeout=", buf, 16)) {
158                 if (sscanf(buf + 16, "%d", &val) != 1)
159                         return -EINVAL;
160                 param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
161         } else if (!strncmp("lprx=", buf, 5)) {
162                 if (sscanf(buf + 5, "%d", &val) != 1)
163                         return -EINVAL;
164                 param = MVM_DEBUGFS_PM_LPRX_ENA;
165         } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
166                 if (sscanf(buf + 20, "%d", &val) != 1)
167                         return -EINVAL;
168                 if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
169                     POWER_LPRX_RSSI_THRESHOLD_MIN)
170                         return -EINVAL;
171                 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
172         } else if (!strncmp("snooze_enable=", buf, 14)) {
173                 if (sscanf(buf + 14, "%d", &val) != 1)
174                         return -EINVAL;
175                 param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
176         } else if (!strncmp("uapsd_misbehaving=", buf, 18)) {
177                 if (sscanf(buf + 18, "%d", &val) != 1)
178                         return -EINVAL;
179                 param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING;
180         } else if (!strncmp("use_ps_poll=", buf, 12)) {
181                 if (sscanf(buf + 12, "%d", &val) != 1)
182                         return -EINVAL;
183                 param = MVM_DEBUGFS_PM_USE_PS_POLL;
184         } else {
185                 return -EINVAL;
186         }
187
188         mutex_lock(&mvm->mutex);
189         iwl_dbgfs_update_pm(mvm, vif, param, val);
190         ret = iwl_mvm_power_update_mac(mvm);
191         mutex_unlock(&mvm->mutex);
192
193         return ret ?: count;
194 }
195
196 static ssize_t iwl_dbgfs_tx_pwr_lmt_read(struct file *file,
197                                          char __user *user_buf,
198                                          size_t count, loff_t *ppos)
199 {
200         struct ieee80211_vif *vif = file->private_data;
201         char buf[64];
202         int bufsz = sizeof(buf);
203         int pos;
204
205         pos = scnprintf(buf, bufsz, "bss limit = %d\n",
206                         vif->bss_conf.txpower);
207
208         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
209 }
210
211 static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
212                                         char __user *user_buf,
213                                         size_t count, loff_t *ppos)
214 {
215         struct ieee80211_vif *vif = file->private_data;
216         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
217         struct iwl_mvm *mvm = mvmvif->mvm;
218         char buf[512];
219         int bufsz = sizeof(buf);
220         int pos;
221
222         pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
223
224         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
225 }
226
227 static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
228                                          char __user *user_buf,
229                                          size_t count, loff_t *ppos)
230 {
231         struct ieee80211_vif *vif = file->private_data;
232         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
233         struct iwl_mvm *mvm = mvmvif->mvm;
234         u8 ap_sta_id;
235         struct ieee80211_chanctx_conf *chanctx_conf;
236         char buf[512];
237         int bufsz = sizeof(buf);
238         int pos = 0;
239         int i;
240
241         mutex_lock(&mvm->mutex);
242
243         ap_sta_id = mvmvif->ap_sta_id;
244
245         switch (ieee80211_vif_type_p2p(vif)) {
246         case NL80211_IFTYPE_ADHOC:
247                 pos += scnprintf(buf+pos, bufsz-pos, "type: ibss\n");
248                 break;
249         case NL80211_IFTYPE_STATION:
250                 pos += scnprintf(buf+pos, bufsz-pos, "type: bss\n");
251                 break;
252         case NL80211_IFTYPE_AP:
253                 pos += scnprintf(buf+pos, bufsz-pos, "type: ap\n");
254                 break;
255         case NL80211_IFTYPE_P2P_CLIENT:
256                 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p client\n");
257                 break;
258         case NL80211_IFTYPE_P2P_GO:
259                 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p go\n");
260                 break;
261         case NL80211_IFTYPE_P2P_DEVICE:
262                 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p dev\n");
263                 break;
264         default:
265                 break;
266         }
267
268         pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
269                          mvmvif->id, mvmvif->color);
270         pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
271                          vif->bss_conf.bssid);
272         pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
273         for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
274                 pos += scnprintf(buf+pos, bufsz-pos,
275                                  "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
276                                  i, mvmvif->queue_params[i].txop,
277                                  mvmvif->queue_params[i].cw_min,
278                                  mvmvif->queue_params[i].cw_max,
279                                  mvmvif->queue_params[i].aifs,
280                                  mvmvif->queue_params[i].uapsd);
281
282         if (vif->type == NL80211_IFTYPE_STATION &&
283             ap_sta_id != IWL_MVM_STATION_COUNT) {
284                 struct ieee80211_sta *sta;
285
286                 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
287                                                 lockdep_is_held(&mvm->mutex));
288                 if (!IS_ERR_OR_NULL(sta)) {
289                         struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
290
291                         pos += scnprintf(buf+pos, bufsz-pos,
292                                          "ap_sta_id %d - reduced Tx power %d\n",
293                                          ap_sta_id,
294                                          mvm_sta->bt_reduced_txpower);
295                 }
296         }
297
298         rcu_read_lock();
299         chanctx_conf = rcu_dereference(vif->chanctx_conf);
300         if (chanctx_conf)
301                 pos += scnprintf(buf+pos, bufsz-pos,
302                                  "idle rx chains %d, active rx chains: %d\n",
303                                  chanctx_conf->rx_chains_static,
304                                  chanctx_conf->rx_chains_dynamic);
305         rcu_read_unlock();
306
307         mutex_unlock(&mvm->mutex);
308
309         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
310 }
311
312 static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
313                                 enum iwl_dbgfs_bf_mask param, int value)
314 {
315         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
316         struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
317
318         dbgfs_bf->mask |= param;
319
320         switch (param) {
321         case MVM_DEBUGFS_BF_ENERGY_DELTA:
322                 dbgfs_bf->bf_energy_delta = value;
323                 break;
324         case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
325                 dbgfs_bf->bf_roaming_energy_delta = value;
326                 break;
327         case MVM_DEBUGFS_BF_ROAMING_STATE:
328                 dbgfs_bf->bf_roaming_state = value;
329                 break;
330         case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
331                 dbgfs_bf->bf_temp_threshold = value;
332                 break;
333         case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
334                 dbgfs_bf->bf_temp_fast_filter = value;
335                 break;
336         case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
337                 dbgfs_bf->bf_temp_slow_filter = value;
338                 break;
339         case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
340                 dbgfs_bf->bf_enable_beacon_filter = value;
341                 break;
342         case MVM_DEBUGFS_BF_DEBUG_FLAG:
343                 dbgfs_bf->bf_debug_flag = value;
344                 break;
345         case MVM_DEBUGFS_BF_ESCAPE_TIMER:
346                 dbgfs_bf->bf_escape_timer = value;
347                 break;
348         case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
349                 dbgfs_bf->ba_enable_beacon_abort = value;
350                 break;
351         case MVM_DEBUGFS_BA_ESCAPE_TIMER:
352                 dbgfs_bf->ba_escape_timer = value;
353                 break;
354         }
355 }
356
357 static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
358                                          size_t count, loff_t *ppos)
359 {
360         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
361         struct iwl_mvm *mvm = mvmvif->mvm;
362         enum iwl_dbgfs_bf_mask param;
363         int value, ret = 0;
364
365         if (!strncmp("bf_energy_delta=", buf, 16)) {
366                 if (sscanf(buf+16, "%d", &value) != 1)
367                         return -EINVAL;
368                 if (value < IWL_BF_ENERGY_DELTA_MIN ||
369                     value > IWL_BF_ENERGY_DELTA_MAX)
370                         return -EINVAL;
371                 param = MVM_DEBUGFS_BF_ENERGY_DELTA;
372         } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
373                 if (sscanf(buf+24, "%d", &value) != 1)
374                         return -EINVAL;
375                 if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
376                     value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
377                         return -EINVAL;
378                 param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
379         } else if (!strncmp("bf_roaming_state=", buf, 17)) {
380                 if (sscanf(buf+17, "%d", &value) != 1)
381                         return -EINVAL;
382                 if (value < IWL_BF_ROAMING_STATE_MIN ||
383                     value > IWL_BF_ROAMING_STATE_MAX)
384                         return -EINVAL;
385                 param = MVM_DEBUGFS_BF_ROAMING_STATE;
386         } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
387                 if (sscanf(buf+18, "%d", &value) != 1)
388                         return -EINVAL;
389                 if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
390                     value > IWL_BF_TEMP_THRESHOLD_MAX)
391                         return -EINVAL;
392                 param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
393         } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
394                 if (sscanf(buf+20, "%d", &value) != 1)
395                         return -EINVAL;
396                 if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
397                     value > IWL_BF_TEMP_FAST_FILTER_MAX)
398                         return -EINVAL;
399                 param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
400         } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
401                 if (sscanf(buf+20, "%d", &value) != 1)
402                         return -EINVAL;
403                 if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
404                     value > IWL_BF_TEMP_SLOW_FILTER_MAX)
405                         return -EINVAL;
406                 param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
407         } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
408                 if (sscanf(buf+24, "%d", &value) != 1)
409                         return -EINVAL;
410                 if (value < 0 || value > 1)
411                         return -EINVAL;
412                 param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
413         } else if (!strncmp("bf_debug_flag=", buf, 14)) {
414                 if (sscanf(buf+14, "%d", &value) != 1)
415                         return -EINVAL;
416                 if (value < 0 || value > 1)
417                         return -EINVAL;
418                 param = MVM_DEBUGFS_BF_DEBUG_FLAG;
419         } else if (!strncmp("bf_escape_timer=", buf, 16)) {
420                 if (sscanf(buf+16, "%d", &value) != 1)
421                         return -EINVAL;
422                 if (value < IWL_BF_ESCAPE_TIMER_MIN ||
423                     value > IWL_BF_ESCAPE_TIMER_MAX)
424                         return -EINVAL;
425                 param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
426         } else if (!strncmp("ba_escape_timer=", buf, 16)) {
427                 if (sscanf(buf+16, "%d", &value) != 1)
428                         return -EINVAL;
429                 if (value < IWL_BA_ESCAPE_TIMER_MIN ||
430                     value > IWL_BA_ESCAPE_TIMER_MAX)
431                         return -EINVAL;
432                 param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
433         } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
434                 if (sscanf(buf+23, "%d", &value) != 1)
435                         return -EINVAL;
436                 if (value < 0 || value > 1)
437                         return -EINVAL;
438                 param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
439         } else {
440                 return -EINVAL;
441         }
442
443         mutex_lock(&mvm->mutex);
444         iwl_dbgfs_update_bf(vif, param, value);
445         if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
446                 ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
447         else
448                 ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
449         mutex_unlock(&mvm->mutex);
450
451         return ret ?: count;
452 }
453
454 static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
455                                         char __user *user_buf,
456                                         size_t count, loff_t *ppos)
457 {
458         struct ieee80211_vif *vif = file->private_data;
459         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
460         char buf[256];
461         int pos = 0;
462         const size_t bufsz = sizeof(buf);
463         struct iwl_beacon_filter_cmd cmd = {
464                 IWL_BF_CMD_CONFIG_DEFAULTS,
465                 .bf_enable_beacon_filter =
466                         cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
467                 .ba_enable_beacon_abort =
468                         cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
469         };
470
471         iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
472         if (mvmvif->bf_data.bf_enabled)
473                 cmd.bf_enable_beacon_filter = cpu_to_le32(1);
474         else
475                 cmd.bf_enable_beacon_filter = 0;
476
477         pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
478                          le32_to_cpu(cmd.bf_energy_delta));
479         pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
480                          le32_to_cpu(cmd.bf_roaming_energy_delta));
481         pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
482                          le32_to_cpu(cmd.bf_roaming_state));
483         pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
484                          le32_to_cpu(cmd.bf_temp_threshold));
485         pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
486                          le32_to_cpu(cmd.bf_temp_fast_filter));
487         pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
488                          le32_to_cpu(cmd.bf_temp_slow_filter));
489         pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
490                          le32_to_cpu(cmd.bf_enable_beacon_filter));
491         pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
492                          le32_to_cpu(cmd.bf_debug_flag));
493         pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
494                          le32_to_cpu(cmd.bf_escape_timer));
495         pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
496                          le32_to_cpu(cmd.ba_escape_timer));
497         pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
498                          le32_to_cpu(cmd.ba_enable_beacon_abort));
499
500         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
501 }
502
503 static inline char *iwl_dbgfs_is_match(char *name, char *buf)
504 {
505         int len = strlen(name);
506
507         return !strncmp(name, buf, len) ? buf + len : NULL;
508 }
509
510 static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif,
511                                           char *buf,
512                                           size_t count, loff_t *ppos)
513 {
514         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
515         struct iwl_mvm *mvm = mvmvif->mvm;
516         u32 value;
517         int ret = -EINVAL;
518         char *data;
519
520         mutex_lock(&mvm->mutex);
521
522         data = iwl_dbgfs_is_match("tof_disabled=", buf);
523         if (data) {
524                 ret = kstrtou32(data, 10, &value);
525                 if (ret == 0)
526                         mvm->tof_data.tof_cfg.tof_disabled = value;
527                 goto out;
528         }
529
530         data = iwl_dbgfs_is_match("one_sided_disabled=", buf);
531         if (data) {
532                 ret = kstrtou32(data, 10, &value);
533                 if (ret == 0)
534                         mvm->tof_data.tof_cfg.one_sided_disabled = value;
535                 goto out;
536         }
537
538         data = iwl_dbgfs_is_match("is_debug_mode=", buf);
539         if (data) {
540                 ret = kstrtou32(data, 10, &value);
541                 if (ret == 0)
542                         mvm->tof_data.tof_cfg.is_debug_mode = value;
543                 goto out;
544         }
545
546         data = iwl_dbgfs_is_match("is_buf=", buf);
547         if (data) {
548                 ret = kstrtou32(data, 10, &value);
549                 if (ret == 0)
550                         mvm->tof_data.tof_cfg.is_buf_required = value;
551                 goto out;
552         }
553
554         data = iwl_dbgfs_is_match("send_tof_cfg=", buf);
555         if (data) {
556                 ret = kstrtou32(data, 10, &value);
557                 if (ret == 0 && value) {
558                         ret = iwl_mvm_tof_config_cmd(mvm);
559                         goto out;
560                 }
561         }
562
563 out:
564         mutex_unlock(&mvm->mutex);
565
566         return ret ?: count;
567 }
568
569 static ssize_t iwl_dbgfs_tof_enable_read(struct file *file,
570                                          char __user *user_buf,
571                                          size_t count, loff_t *ppos)
572 {
573         struct ieee80211_vif *vif = file->private_data;
574         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
575         struct iwl_mvm *mvm = mvmvif->mvm;
576         char buf[256];
577         int pos = 0;
578         const size_t bufsz = sizeof(buf);
579         struct iwl_tof_config_cmd *cmd;
580
581         cmd = &mvm->tof_data.tof_cfg;
582
583         mutex_lock(&mvm->mutex);
584
585         pos += scnprintf(buf + pos, bufsz - pos, "tof_disabled = %d\n",
586                          cmd->tof_disabled);
587         pos += scnprintf(buf + pos, bufsz - pos, "one_sided_disabled = %d\n",
588                          cmd->one_sided_disabled);
589         pos += scnprintf(buf + pos, bufsz - pos, "is_debug_mode = %d\n",
590                          cmd->is_debug_mode);
591         pos += scnprintf(buf + pos, bufsz - pos, "is_buf_required = %d\n",
592                          cmd->is_buf_required);
593
594         mutex_unlock(&mvm->mutex);
595
596         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
597 }
598
599 static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif,
600                                                     char *buf,
601                                                     size_t count, loff_t *ppos)
602 {
603         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
604         struct iwl_mvm *mvm = mvmvif->mvm;
605         u32 value;
606         int ret = 0;
607         char *data;
608
609         mutex_lock(&mvm->mutex);
610
611         data = iwl_dbgfs_is_match("burst_period=", buf);
612         if (data) {
613                 ret = kstrtou32(data, 10, &value);
614                 if (!ret)
615                         mvm->tof_data.responder_cfg.burst_period =
616                                                         cpu_to_le16(value);
617                 goto out;
618         }
619
620         data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
621         if (data) {
622                 ret = kstrtou32(data, 10, &value);
623                 if (ret == 0)
624                         mvm->tof_data.responder_cfg.min_delta_ftm = value;
625                 goto out;
626         }
627
628         data = iwl_dbgfs_is_match("burst_duration=", buf);
629         if (data) {
630                 ret = kstrtou32(data, 10, &value);
631                 if (ret == 0)
632                         mvm->tof_data.responder_cfg.burst_duration = value;
633                 goto out;
634         }
635
636         data = iwl_dbgfs_is_match("num_of_burst_exp=", buf);
637         if (data) {
638                 ret = kstrtou32(data, 10, &value);
639                 if (ret == 0)
640                         mvm->tof_data.responder_cfg.num_of_burst_exp = value;
641                 goto out;
642         }
643
644         data = iwl_dbgfs_is_match("abort_responder=", buf);
645         if (data) {
646                 ret = kstrtou32(data, 10, &value);
647                 if (ret == 0)
648                         mvm->tof_data.responder_cfg.abort_responder = value;
649                 goto out;
650         }
651
652         data = iwl_dbgfs_is_match("get_ch_est=", buf);
653         if (data) {
654                 ret = kstrtou32(data, 10, &value);
655                 if (ret == 0)
656                         mvm->tof_data.responder_cfg.get_ch_est = value;
657                 goto out;
658         }
659
660         data = iwl_dbgfs_is_match("recv_sta_req_params=", buf);
661         if (data) {
662                 ret = kstrtou32(data, 10, &value);
663                 if (ret == 0)
664                         mvm->tof_data.responder_cfg.recv_sta_req_params = value;
665                 goto out;
666         }
667
668         data = iwl_dbgfs_is_match("channel_num=", buf);
669         if (data) {
670                 ret = kstrtou32(data, 10, &value);
671                 if (ret == 0)
672                         mvm->tof_data.responder_cfg.channel_num = value;
673                 goto out;
674         }
675
676         data = iwl_dbgfs_is_match("bandwidth=", buf);
677         if (data) {
678                 ret = kstrtou32(data, 10, &value);
679                 if (ret == 0)
680                         mvm->tof_data.responder_cfg.bandwidth = value;
681                 goto out;
682         }
683
684         data = iwl_dbgfs_is_match("rate=", buf);
685         if (data) {
686                 ret = kstrtou32(data, 10, &value);
687                 if (ret == 0)
688                         mvm->tof_data.responder_cfg.rate = value;
689                 goto out;
690         }
691
692         data = iwl_dbgfs_is_match("bssid=", buf);
693         if (data) {
694                 u8 *mac = mvm->tof_data.responder_cfg.bssid;
695
696                 if (!mac_pton(data, mac)) {
697                         ret = -EINVAL;
698                         goto out;
699                 }
700         }
701
702         data = iwl_dbgfs_is_match("tsf_timer_offset_msecs=", buf);
703         if (data) {
704                 ret = kstrtou32(data, 10, &value);
705                 if (ret == 0)
706                         mvm->tof_data.responder_cfg.tsf_timer_offset_msecs =
707                                                         cpu_to_le16(value);
708                 goto out;
709         }
710
711         data = iwl_dbgfs_is_match("toa_offset=", buf);
712         if (data) {
713                 ret = kstrtou32(data, 10, &value);
714                 if (ret == 0)
715                         mvm->tof_data.responder_cfg.toa_offset =
716                                                         cpu_to_le16(value);
717                 goto out;
718         }
719
720         data = iwl_dbgfs_is_match("center_freq=", buf);
721         if (data) {
722                 struct iwl_tof_responder_config_cmd *cmd =
723                         &mvm->tof_data.responder_cfg;
724
725                 ret = kstrtou32(data, 10, &value);
726                 if (ret == 0 && value) {
727                         enum nl80211_band band = (cmd->channel_num <= 14) ?
728                                                    NL80211_BAND_2GHZ :
729                                                    NL80211_BAND_5GHZ;
730                         struct ieee80211_channel chn = {
731                                 .band = band,
732                                 .center_freq = ieee80211_channel_to_frequency(
733                                         cmd->channel_num, band),
734                                 };
735                         struct cfg80211_chan_def chandef = {
736                                 .chan =  &chn,
737                                 .center_freq1 =
738                                         ieee80211_channel_to_frequency(value,
739                                                                        band),
740                         };
741
742                         cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef);
743                 }
744                 goto out;
745         }
746
747         data = iwl_dbgfs_is_match("ftm_per_burst=", buf);
748         if (data) {
749                 ret = kstrtou32(data, 10, &value);
750                 if (ret == 0)
751                         mvm->tof_data.responder_cfg.ftm_per_burst = value;
752                 goto out;
753         }
754
755         data = iwl_dbgfs_is_match("ftm_resp_ts_avail=", buf);
756         if (data) {
757                 ret = kstrtou32(data, 10, &value);
758                 if (ret == 0)
759                         mvm->tof_data.responder_cfg.ftm_resp_ts_avail = value;
760                 goto out;
761         }
762
763         data = iwl_dbgfs_is_match("asap_mode=", buf);
764         if (data) {
765                 ret = kstrtou32(data, 10, &value);
766                 if (ret == 0)
767                         mvm->tof_data.responder_cfg.asap_mode = value;
768                 goto out;
769         }
770
771         data = iwl_dbgfs_is_match("send_responder_cfg=", buf);
772         if (data) {
773                 ret = kstrtou32(data, 10, &value);
774                 if (ret == 0 && value) {
775                         ret = iwl_mvm_tof_responder_cmd(mvm, vif);
776                         goto out;
777                 }
778         }
779
780 out:
781         mutex_unlock(&mvm->mutex);
782
783         return ret ?: count;
784 }
785
786 static ssize_t iwl_dbgfs_tof_responder_params_read(struct file *file,
787                                                    char __user *user_buf,
788                                                    size_t count, loff_t *ppos)
789 {
790         struct ieee80211_vif *vif = file->private_data;
791         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
792         struct iwl_mvm *mvm = mvmvif->mvm;
793         char buf[256];
794         int pos = 0;
795         const size_t bufsz = sizeof(buf);
796         struct iwl_tof_responder_config_cmd *cmd;
797
798         cmd = &mvm->tof_data.responder_cfg;
799
800         mutex_lock(&mvm->mutex);
801
802         pos += scnprintf(buf + pos, bufsz - pos, "burst_period = %d\n",
803                          le16_to_cpu(cmd->burst_period));
804         pos += scnprintf(buf + pos, bufsz - pos, "burst_duration = %d\n",
805                          cmd->burst_duration);
806         pos += scnprintf(buf + pos, bufsz - pos, "bandwidth = %d\n",
807                          cmd->bandwidth);
808         pos += scnprintf(buf + pos, bufsz - pos, "channel_num = %d\n",
809                          cmd->channel_num);
810         pos += scnprintf(buf + pos, bufsz - pos, "ctrl_ch_position = 0x%x\n",
811                          cmd->ctrl_ch_position);
812         pos += scnprintf(buf + pos, bufsz - pos, "bssid = %pM\n",
813                          cmd->bssid);
814         pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %d\n",
815                          cmd->min_delta_ftm);
816         pos += scnprintf(buf + pos, bufsz - pos, "num_of_burst_exp = %d\n",
817                          cmd->num_of_burst_exp);
818         pos += scnprintf(buf + pos, bufsz - pos, "rate = %d\n", cmd->rate);
819         pos += scnprintf(buf + pos, bufsz - pos, "abort_responder = %d\n",
820                          cmd->abort_responder);
821         pos += scnprintf(buf + pos, bufsz - pos, "get_ch_est = %d\n",
822                          cmd->get_ch_est);
823         pos += scnprintf(buf + pos, bufsz - pos, "recv_sta_req_params = %d\n",
824                          cmd->recv_sta_req_params);
825         pos += scnprintf(buf + pos, bufsz - pos, "ftm_per_burst = %d\n",
826                          cmd->ftm_per_burst);
827         pos += scnprintf(buf + pos, bufsz - pos, "ftm_resp_ts_avail = %d\n",
828                          cmd->ftm_resp_ts_avail);
829         pos += scnprintf(buf + pos, bufsz - pos, "asap_mode = %d\n",
830                          cmd->asap_mode);
831         pos += scnprintf(buf + pos, bufsz - pos,
832                          "tsf_timer_offset_msecs = %d\n",
833                          le16_to_cpu(cmd->tsf_timer_offset_msecs));
834         pos += scnprintf(buf + pos, bufsz - pos, "toa_offset = %d\n",
835                          le16_to_cpu(cmd->toa_offset));
836
837         mutex_unlock(&mvm->mutex);
838
839         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
840 }
841
842 static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
843                                                  char *buf, size_t count,
844                                                  loff_t *ppos)
845 {
846         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
847         struct iwl_mvm *mvm = mvmvif->mvm;
848         u32 value;
849         int ret = 0;
850         char *data;
851
852         mutex_lock(&mvm->mutex);
853
854         data = iwl_dbgfs_is_match("request_id=", buf);
855         if (data) {
856                 ret = kstrtou32(data, 10, &value);
857                 if (ret == 0)
858                         mvm->tof_data.range_req.request_id = value;
859                 goto out;
860         }
861
862         data = iwl_dbgfs_is_match("initiator=", buf);
863         if (data) {
864                 ret = kstrtou32(data, 10, &value);
865                 if (ret == 0)
866                         mvm->tof_data.range_req.initiator = value;
867                 goto out;
868         }
869
870         data = iwl_dbgfs_is_match("one_sided_los_disable=", buf);
871         if (data) {
872                 ret = kstrtou32(data, 10, &value);
873                 if (ret == 0)
874                         mvm->tof_data.range_req.one_sided_los_disable = value;
875                 goto out;
876         }
877
878         data = iwl_dbgfs_is_match("req_timeout=", buf);
879         if (data) {
880                 ret = kstrtou32(data, 10, &value);
881                 if (ret == 0)
882                         mvm->tof_data.range_req.req_timeout = value;
883                 goto out;
884         }
885
886         data = iwl_dbgfs_is_match("report_policy=", buf);
887         if (data) {
888                 ret = kstrtou32(data, 10, &value);
889                 if (ret == 0)
890                         mvm->tof_data.range_req.report_policy = value;
891                 goto out;
892         }
893
894         data = iwl_dbgfs_is_match("macaddr_random=", buf);
895         if (data) {
896                 ret = kstrtou32(data, 10, &value);
897                 if (ret == 0)
898                         mvm->tof_data.range_req.macaddr_random = value;
899                 goto out;
900         }
901
902         data = iwl_dbgfs_is_match("num_of_ap=", buf);
903         if (data) {
904                 ret = kstrtou32(data, 10, &value);
905                 if (ret == 0)
906                         mvm->tof_data.range_req.num_of_ap = value;
907                 goto out;
908         }
909
910         data = iwl_dbgfs_is_match("macaddr_template=", buf);
911         if (data) {
912                 u8 mac[ETH_ALEN];
913
914                 if (!mac_pton(data, mac)) {
915                         ret = -EINVAL;
916                         goto out;
917                 }
918                 memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN);
919                 goto out;
920         }
921
922         data = iwl_dbgfs_is_match("macaddr_mask=", buf);
923         if (data) {
924                 u8 mac[ETH_ALEN];
925
926                 if (!mac_pton(data, mac)) {
927                         ret = -EINVAL;
928                         goto out;
929                 }
930                 memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN);
931                 goto out;
932         }
933
934         data = iwl_dbgfs_is_match("ap=", buf);
935         if (data) {
936                 struct iwl_tof_range_req_ap_entry ap = {};
937                 int size = sizeof(struct iwl_tof_range_req_ap_entry);
938                 u16 burst_period;
939                 u8 *mac = ap.bssid;
940                 unsigned int i;
941
942                 if (sscanf(data, "%u %hhd %hhd %hhd"
943                            "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
944                            "%hhd %hhd %hd"
945                            "%hhd %hhd %d"
946                            "%hhx %hhd %hhd %hhd",
947                            &i, &ap.channel_num, &ap.bandwidth,
948                            &ap.ctrl_ch_position,
949                            mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5,
950                            &ap.measure_type, &ap.num_of_bursts,
951                            &burst_period,
952                            &ap.samples_per_burst, &ap.retries_per_sample,
953                            &ap.tsf_delta, &ap.location_req, &ap.asap_mode,
954                            &ap.enable_dyn_ack, &ap.rssi) != 20) {
955                         ret = -EINVAL;
956                         goto out;
957                 }
958                 if (i >= IWL_MVM_TOF_MAX_APS) {
959                         IWL_ERR(mvm, "Invalid AP index %d\n", i);
960                         ret = -EINVAL;
961                         goto out;
962                 }
963
964                 ap.burst_period = cpu_to_le16(burst_period);
965
966                 memcpy(&mvm->tof_data.range_req.ap[i], &ap, size);
967                 goto out;
968         }
969
970         data = iwl_dbgfs_is_match("send_range_request=", buf);
971         if (data) {
972                 ret = kstrtou32(data, 10, &value);
973                 if (ret == 0 && value)
974                         ret = iwl_mvm_tof_range_request_cmd(mvm, vif);
975                 goto out;
976         }
977
978         ret = -EINVAL;
979 out:
980         mutex_unlock(&mvm->mutex);
981         return ret ?: count;
982 }
983
984 static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file,
985                                                 char __user *user_buf,
986                                                 size_t count, loff_t *ppos)
987 {
988         struct ieee80211_vif *vif = file->private_data;
989         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
990         struct iwl_mvm *mvm = mvmvif->mvm;
991         char buf[512];
992         int pos = 0;
993         const size_t bufsz = sizeof(buf);
994         struct iwl_tof_range_req_cmd *cmd;
995         int i;
996
997         cmd = &mvm->tof_data.range_req;
998
999         mutex_lock(&mvm->mutex);
1000
1001         pos += scnprintf(buf + pos, bufsz - pos, "request_id= %d\n",
1002                          cmd->request_id);
1003         pos += scnprintf(buf + pos, bufsz - pos, "initiator= %d\n",
1004                          cmd->initiator);
1005         pos += scnprintf(buf + pos, bufsz - pos, "one_sided_los_disable = %d\n",
1006                          cmd->one_sided_los_disable);
1007         pos += scnprintf(buf + pos, bufsz - pos, "req_timeout= %d\n",
1008                          cmd->req_timeout);
1009         pos += scnprintf(buf + pos, bufsz - pos, "report_policy= %d\n",
1010                          cmd->report_policy);
1011         pos += scnprintf(buf + pos, bufsz - pos, "macaddr_random= %d\n",
1012                          cmd->macaddr_random);
1013         pos += scnprintf(buf + pos, bufsz - pos, "macaddr_template= %pM\n",
1014                          cmd->macaddr_template);
1015         pos += scnprintf(buf + pos, bufsz - pos, "macaddr_mask= %pM\n",
1016                          cmd->macaddr_mask);
1017         pos += scnprintf(buf + pos, bufsz - pos, "num_of_ap= %d\n",
1018                          cmd->num_of_ap);
1019         for (i = 0; i < cmd->num_of_ap; i++) {
1020                 struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i];
1021
1022                 pos += scnprintf(buf + pos, bufsz - pos,
1023                                 "ap %.2d: channel_num=%hhd bw=%hhd"
1024                                 " control=%hhd bssid=%pM type=%hhd"
1025                                 " num_of_bursts=%hhd burst_period=%hd ftm=%hhd"
1026                                 " retries=%hhd tsf_delta=%d"
1027                                 " tsf_delta_direction=%hhd location_req=0x%hhx "
1028                                 " asap=%hhd enable=%hhd rssi=%hhd\n",
1029                                 i, ap->channel_num, ap->bandwidth,
1030                                 ap->ctrl_ch_position, ap->bssid,
1031                                 ap->measure_type, ap->num_of_bursts,
1032                                 ap->burst_period, ap->samples_per_burst,
1033                                 ap->retries_per_sample, ap->tsf_delta,
1034                                 ap->tsf_delta_direction,
1035                                 ap->location_req, ap->asap_mode,
1036                                 ap->enable_dyn_ack, ap->rssi);
1037         }
1038
1039         mutex_unlock(&mvm->mutex);
1040
1041         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1042 }
1043
1044 static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif,
1045                                                  char *buf,
1046                                                  size_t count, loff_t *ppos)
1047 {
1048         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1049         struct iwl_mvm *mvm = mvmvif->mvm;
1050         u32 value;
1051         int ret = 0;
1052         char *data;
1053
1054         mutex_lock(&mvm->mutex);
1055
1056         data = iwl_dbgfs_is_match("tsf_timer_offset_msec=", buf);
1057         if (data) {
1058                 ret = kstrtou32(data, 10, &value);
1059                 if (ret == 0)
1060                         mvm->tof_data.range_req_ext.tsf_timer_offset_msec =
1061                                                         cpu_to_le16(value);
1062                 goto out;
1063         }
1064
1065         data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
1066         if (data) {
1067                 ret = kstrtou32(data, 10, &value);
1068                 if (ret == 0)
1069                         mvm->tof_data.range_req_ext.min_delta_ftm = value;
1070                 goto out;
1071         }
1072
1073         data = iwl_dbgfs_is_match("ftm_format_and_bw20M=", buf);
1074         if (data) {
1075                 ret = kstrtou32(data, 10, &value);
1076                 if (ret == 0)
1077                         mvm->tof_data.range_req_ext.ftm_format_and_bw20M =
1078                                                                         value;
1079                 goto out;
1080         }
1081
1082         data = iwl_dbgfs_is_match("ftm_format_and_bw40M=", buf);
1083         if (data) {
1084                 ret = kstrtou32(data, 10, &value);
1085                 if (ret == 0)
1086                         mvm->tof_data.range_req_ext.ftm_format_and_bw40M =
1087                                                                         value;
1088                 goto out;
1089         }
1090
1091         data = iwl_dbgfs_is_match("ftm_format_and_bw80M=", buf);
1092         if (data) {
1093                 ret = kstrtou32(data, 10, &value);
1094                 if (ret == 0)
1095                         mvm->tof_data.range_req_ext.ftm_format_and_bw80M =
1096                                                                         value;
1097                 goto out;
1098         }
1099
1100         data = iwl_dbgfs_is_match("send_range_req_ext=", buf);
1101         if (data) {
1102                 ret = kstrtou32(data, 10, &value);
1103                 if (ret == 0 && value)
1104                         ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif);
1105                 goto out;
1106         }
1107
1108         ret = -EINVAL;
1109 out:
1110         mutex_unlock(&mvm->mutex);
1111         return ret ?: count;
1112 }
1113
1114 static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file,
1115                                                 char __user *user_buf,
1116                                                 size_t count, loff_t *ppos)
1117 {
1118         struct ieee80211_vif *vif = file->private_data;
1119         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1120         struct iwl_mvm *mvm = mvmvif->mvm;
1121         char buf[256];
1122         int pos = 0;
1123         const size_t bufsz = sizeof(buf);
1124         struct iwl_tof_range_req_ext_cmd *cmd;
1125
1126         cmd = &mvm->tof_data.range_req_ext;
1127
1128         mutex_lock(&mvm->mutex);
1129
1130         pos += scnprintf(buf + pos, bufsz - pos,
1131                          "tsf_timer_offset_msec = %hd\n",
1132                          cmd->tsf_timer_offset_msec);
1133         pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n",
1134                          cmd->min_delta_ftm);
1135         pos += scnprintf(buf + pos, bufsz - pos,
1136                          "ftm_format_and_bw20M = %hhd\n",
1137                          cmd->ftm_format_and_bw20M);
1138         pos += scnprintf(buf + pos, bufsz - pos,
1139                          "ftm_format_and_bw40M = %hhd\n",
1140                          cmd->ftm_format_and_bw40M);
1141         pos += scnprintf(buf + pos, bufsz - pos,
1142                          "ftm_format_and_bw80M = %hhd\n",
1143                          cmd->ftm_format_and_bw80M);
1144
1145         mutex_unlock(&mvm->mutex);
1146         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1147 }
1148
1149 static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif,
1150                                                char *buf,
1151                                                size_t count, loff_t *ppos)
1152 {
1153         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1154         struct iwl_mvm *mvm = mvmvif->mvm;
1155         u32 value;
1156         int abort_id, ret = 0;
1157         char *data;
1158
1159         mutex_lock(&mvm->mutex);
1160
1161         data = iwl_dbgfs_is_match("abort_id=", buf);
1162         if (data) {
1163                 ret = kstrtou32(data, 10, &value);
1164                 if (ret == 0)
1165                         mvm->tof_data.last_abort_id = value;
1166                 goto out;
1167         }
1168
1169         data = iwl_dbgfs_is_match("send_range_abort=", buf);
1170         if (data) {
1171                 ret = kstrtou32(data, 10, &value);
1172                 if (ret == 0 && value) {
1173                         abort_id = mvm->tof_data.last_abort_id;
1174                         ret = iwl_mvm_tof_range_abort_cmd(mvm, abort_id);
1175                         goto out;
1176                 }
1177         }
1178
1179 out:
1180         mutex_unlock(&mvm->mutex);
1181         return ret ?: count;
1182 }
1183
1184 static ssize_t iwl_dbgfs_tof_range_abort_read(struct file *file,
1185                                               char __user *user_buf,
1186                                               size_t count, loff_t *ppos)
1187 {
1188         struct ieee80211_vif *vif = file->private_data;
1189         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1190         struct iwl_mvm *mvm = mvmvif->mvm;
1191         char buf[32];
1192         int pos = 0;
1193         const size_t bufsz = sizeof(buf);
1194         int last_abort_id;
1195
1196         mutex_lock(&mvm->mutex);
1197         last_abort_id = mvm->tof_data.last_abort_id;
1198         mutex_unlock(&mvm->mutex);
1199
1200         pos += scnprintf(buf + pos, bufsz - pos, "last_abort_id = %d\n",
1201                          last_abort_id);
1202         return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1203 }
1204
1205 static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file,
1206                                                  char __user *user_buf,
1207                                                  size_t count, loff_t *ppos)
1208 {
1209         struct ieee80211_vif *vif = file->private_data;
1210         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1211         struct iwl_mvm *mvm = mvmvif->mvm;
1212         char *buf;
1213         int pos = 0;
1214         const size_t bufsz = sizeof(struct iwl_tof_range_rsp_ntfy) + 256;
1215         struct iwl_tof_range_rsp_ntfy *cmd;
1216         int i, ret;
1217
1218         buf = kzalloc(bufsz, GFP_KERNEL);
1219         if (!buf)
1220                 return -ENOMEM;
1221
1222         mutex_lock(&mvm->mutex);
1223         cmd = &mvm->tof_data.range_resp;
1224
1225         pos += scnprintf(buf + pos, bufsz - pos, "request_id = %d\n",
1226                          cmd->request_id);
1227         pos += scnprintf(buf + pos, bufsz - pos, "status = %d\n",
1228                          cmd->request_status);
1229         pos += scnprintf(buf + pos, bufsz - pos, "last_in_batch = %d\n",
1230                          cmd->last_in_batch);
1231         pos += scnprintf(buf + pos, bufsz - pos, "num_of_aps = %d\n",
1232                          cmd->num_of_aps);
1233         for (i = 0; i < cmd->num_of_aps; i++) {
1234                 struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i];
1235
1236                 pos += scnprintf(buf + pos, bufsz - pos,
1237                                 "ap %.2d: bssid=%pM status=%hhd bw=%hhd"
1238                                 " rtt=%d rtt_var=%d rtt_spread=%d"
1239                                 " rssi=%hhd  rssi_spread=%hhd"
1240                                 " range=%d range_var=%d"
1241                                 " time_stamp=%d\n",
1242                                 i, ap->bssid, ap->measure_status,
1243                                 ap->measure_bw,
1244                                 ap->rtt, ap->rtt_variance, ap->rtt_spread,
1245                                 ap->rssi, ap->rssi_spread, ap->range,
1246                                 ap->range_variance, ap->timestamp);
1247         }
1248         mutex_unlock(&mvm->mutex);
1249
1250         ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1251         kfree(buf);
1252         return ret;
1253 }
1254
1255 static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
1256                                            size_t count, loff_t *ppos)
1257 {
1258         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1259         struct iwl_mvm *mvm = mvmvif->mvm;
1260         bool prev;
1261         u8 value;
1262         int ret;
1263
1264         ret = kstrtou8(buf, 0, &value);
1265         if (ret)
1266                 return ret;
1267         if (value > 1)
1268                 return -EINVAL;
1269
1270         mutex_lock(&mvm->mutex);
1271         prev = iwl_mvm_vif_low_latency(mvmvif);
1272         mvmvif->low_latency_dbgfs = value;
1273         iwl_mvm_update_low_latency(mvm, vif, prev);
1274         mutex_unlock(&mvm->mutex);
1275
1276         return count;
1277 }
1278
1279 static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
1280                                           char __user *user_buf,
1281                                           size_t count, loff_t *ppos)
1282 {
1283         struct ieee80211_vif *vif = file->private_data;
1284         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1285         char buf[30] = {};
1286         int len;
1287
1288         len = snprintf(buf, sizeof(buf) - 1,
1289                        "traffic=%d\ndbgfs=%d\nvcmd=%d\n",
1290                        mvmvif->low_latency_traffic,
1291                        mvmvif->low_latency_dbgfs,
1292                        mvmvif->low_latency_vcmd);
1293         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1294 }
1295
1296 static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file,
1297                                                 char __user *user_buf,
1298                                                 size_t count, loff_t *ppos)
1299 {
1300         struct ieee80211_vif *vif = file->private_data;
1301         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1302         char buf[20];
1303         int len;
1304
1305         len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid);
1306         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1307 }
1308
1309 static ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif,
1310                                                  char *buf, size_t count,
1311                                                  loff_t *ppos)
1312 {
1313         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1314         struct iwl_mvm *mvm = mvmvif->mvm;
1315         bool ret;
1316
1317         mutex_lock(&mvm->mutex);
1318         ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid);
1319         mutex_unlock(&mvm->mutex);
1320
1321         return ret ? count : -EINVAL;
1322 }
1323
1324 static ssize_t iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif *vif, char *buf,
1325                                           size_t count, loff_t *ppos)
1326 {
1327         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1328         struct iwl_mvm *mvm = mvmvif->mvm;
1329         struct ieee80211_chanctx_conf *chanctx_conf;
1330         struct iwl_mvm_phy_ctxt *phy_ctxt;
1331         u16 value;
1332         int ret;
1333
1334         ret = kstrtou16(buf, 0, &value);
1335         if (ret)
1336                 return ret;
1337
1338         mutex_lock(&mvm->mutex);
1339         rcu_read_lock();
1340
1341         chanctx_conf = rcu_dereference(vif->chanctx_conf);
1342         /* make sure the channel context is assigned */
1343         if (!chanctx_conf) {
1344                 rcu_read_unlock();
1345                 mutex_unlock(&mvm->mutex);
1346                 return -EINVAL;
1347         }
1348
1349         phy_ctxt = &mvm->phy_ctxts[*(u16 *)chanctx_conf->drv_priv];
1350         rcu_read_unlock();
1351
1352         mvm->dbgfs_rx_phyinfo = value;
1353
1354         ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chanctx_conf->min_def,
1355                                        chanctx_conf->rx_chains_static,
1356                                        chanctx_conf->rx_chains_dynamic);
1357         mutex_unlock(&mvm->mutex);
1358
1359         return ret ?: count;
1360 }
1361
1362 static ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file,
1363                                          char __user *user_buf,
1364                                          size_t count, loff_t *ppos)
1365 {
1366         struct ieee80211_vif *vif = file->private_data;
1367         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1368         char buf[8];
1369
1370         snprintf(buf, sizeof(buf), "0x%04x\n", mvmvif->mvm->dbgfs_rx_phyinfo);
1371
1372         return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
1373 }
1374
1375 static void iwl_dbgfs_quota_check(void *data, u8 *mac,
1376                                   struct ieee80211_vif *vif)
1377 {
1378         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1379         int *ret = data;
1380
1381         if (mvmvif->dbgfs_quota_min)
1382                 *ret = -EINVAL;
1383 }
1384
1385 static ssize_t iwl_dbgfs_quota_min_write(struct ieee80211_vif *vif, char *buf,
1386                                          size_t count, loff_t *ppos)
1387 {
1388         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1389         struct iwl_mvm *mvm = mvmvif->mvm;
1390         u16 value;
1391         int ret;
1392
1393         ret = kstrtou16(buf, 0, &value);
1394         if (ret)
1395                 return ret;
1396
1397         if (value > 95)
1398                 return -EINVAL;
1399
1400         mutex_lock(&mvm->mutex);
1401
1402         mvmvif->dbgfs_quota_min = 0;
1403         ieee80211_iterate_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1404                                      iwl_dbgfs_quota_check, &ret);
1405         if (ret == 0) {
1406                 mvmvif->dbgfs_quota_min = value;
1407                 iwl_mvm_update_quotas(mvm, false, NULL);
1408         }
1409         mutex_unlock(&mvm->mutex);
1410
1411         return ret ?: count;
1412 }
1413
1414 static ssize_t iwl_dbgfs_quota_min_read(struct file *file,
1415                                         char __user *user_buf,
1416                                         size_t count, loff_t *ppos)
1417 {
1418         struct ieee80211_vif *vif = file->private_data;
1419         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1420         char buf[10];
1421         int len;
1422
1423         len = snprintf(buf, sizeof(buf), "%d\n", mvmvif->dbgfs_quota_min);
1424
1425         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1426 }
1427
1428 static const char * const chanwidths[] = {
1429         [NL80211_CHAN_WIDTH_20_NOHT] = "noht",
1430         [NL80211_CHAN_WIDTH_20] = "ht20",
1431         [NL80211_CHAN_WIDTH_40] = "ht40",
1432         [NL80211_CHAN_WIDTH_80] = "vht80",
1433         [NL80211_CHAN_WIDTH_80P80] = "vht80p80",
1434         [NL80211_CHAN_WIDTH_160] = "vht160",
1435 };
1436
1437 static bool iwl_mvm_lqm_notif_wait(struct iwl_notif_wait_data *notif_wait,
1438                                    struct iwl_rx_packet *pkt, void *data)
1439 {
1440         struct ieee80211_vif *vif = data;
1441         struct iwl_mvm *mvm =
1442                 container_of(notif_wait, struct iwl_mvm, notif_wait);
1443         struct iwl_link_qual_msrmnt_notif *report = (void *)pkt->data;
1444         u32 num_of_stations = le32_to_cpu(report->number_of_stations);
1445         int i;
1446
1447         IWL_INFO(mvm, "LQM report:\n");
1448         IWL_INFO(mvm, "\tstatus: %d\n", report->status);
1449         IWL_INFO(mvm, "\tmacID: %d\n", le32_to_cpu(report->mac_id));
1450         IWL_INFO(mvm, "\ttx_frame_dropped: %d\n",
1451                  le32_to_cpu(report->tx_frame_dropped));
1452         IWL_INFO(mvm, "\ttime_in_measurement_window: %d us\n",
1453                  le32_to_cpu(report->time_in_measurement_window));
1454         IWL_INFO(mvm, "\ttotal_air_time_other_stations: %d\n",
1455                  le32_to_cpu(report->total_air_time_other_stations));
1456         IWL_INFO(mvm, "\tchannel_freq: %d\n",
1457                  vif->bss_conf.chandef.center_freq1);
1458         IWL_INFO(mvm, "\tchannel_width: %s\n",
1459                  chanwidths[vif->bss_conf.chandef.width]);
1460         IWL_INFO(mvm, "\tnumber_of_stations: %d\n", num_of_stations);
1461         for (i = 0; i < num_of_stations; i++)
1462                 IWL_INFO(mvm, "\t\tsta[%d]: %d\n", i,
1463                          report->frequent_stations_air_time[i]);
1464
1465         return true;
1466 }
1467
1468 static ssize_t iwl_dbgfs_lqm_send_cmd_write(struct ieee80211_vif *vif,
1469                                             char *buf, size_t count,
1470                                             loff_t *ppos)
1471 {
1472         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1473         struct iwl_mvm *mvm = mvmvif->mvm;
1474         struct iwl_notification_wait wait_lqm_notif;
1475         static u16 lqm_notif[] = {
1476                 WIDE_ID(MAC_CONF_GROUP,
1477                         LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF)
1478         };
1479         int err;
1480         u32 duration;
1481         u32 timeout;
1482
1483         if (sscanf(buf, "%d,%d", &duration, &timeout) != 2)
1484                 return -EINVAL;
1485
1486         iwl_init_notification_wait(&mvm->notif_wait, &wait_lqm_notif,
1487                                    lqm_notif, ARRAY_SIZE(lqm_notif),
1488                                    iwl_mvm_lqm_notif_wait, vif);
1489         mutex_lock(&mvm->mutex);
1490         err = iwl_mvm_send_lqm_cmd(vif, LQM_CMD_OPERATION_START_MEASUREMENT,
1491                                    duration, timeout);
1492         mutex_unlock(&mvm->mutex);
1493
1494         if (err) {
1495                 IWL_ERR(mvm, "Failed to send lqm cmdf(err=%d)\n", err);
1496                 iwl_remove_notification(&mvm->notif_wait, &wait_lqm_notif);
1497                 return err;
1498         }
1499
1500         /* wait for 2 * timeout (safety guard) and convert to jiffies*/
1501         timeout = msecs_to_jiffies((timeout * 2) / 1000);
1502
1503         err = iwl_wait_notification(&mvm->notif_wait, &wait_lqm_notif,
1504                                     timeout);
1505         if (err)
1506                 IWL_ERR(mvm, "Getting lqm notif timed out\n");
1507
1508         return count;
1509 }
1510
1511 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1512         _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1513 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1514         _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1515 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do {               \
1516                 if (!debugfs_create_file(#name, mode, parent, vif,      \
1517                                          &iwl_dbgfs_##name##_ops))      \
1518                         goto err;                                       \
1519         } while (0)
1520
1521 MVM_DEBUGFS_READ_FILE_OPS(mac_params);
1522 MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
1523 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
1524 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
1525 MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
1526 MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
1527 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
1528 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable, 32);
1529 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request, 512);
1530 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32);
1531 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32);
1532 MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
1533 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
1534 MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
1535 MVM_DEBUGFS_WRITE_FILE_OPS(lqm_send_cmd, 64);
1536
1537 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1538 {
1539         struct dentry *dbgfs_dir = vif->debugfs_dir;
1540         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1541         char buf[100];
1542
1543         /*
1544          * Check if debugfs directory already exist before creating it.
1545          * This may happen when, for example, resetting hw or suspend-resume
1546          */
1547         if (!dbgfs_dir || mvmvif->dbgfs_dir)
1548                 return;
1549
1550         mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
1551
1552         if (!mvmvif->dbgfs_dir) {
1553                 IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
1554                         dbgfs_dir->d_name.name);
1555                 return;
1556         }
1557
1558         if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
1559             ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
1560              (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
1561               mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
1562                 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
1563                                          S_IRUSR);
1564
1565         MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, S_IRUSR);
1566         MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR);
1567         MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir,
1568                                  S_IRUSR | S_IWUSR);
1569         MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir,
1570                                  S_IRUSR | S_IWUSR);
1571         MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir,
1572                                  S_IRUSR | S_IWUSR);
1573         MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir,
1574                                  S_IRUSR | S_IWUSR);
1575         MVM_DEBUGFS_ADD_FILE_VIF(lqm_send_cmd, mvmvif->dbgfs_dir, S_IWUSR);
1576
1577         if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
1578             mvmvif == mvm->bf_allowed_vif)
1579                 MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir,
1580                                          S_IRUSR | S_IWUSR);
1581
1582         if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT) &&
1583             !vif->p2p && (vif->type != NL80211_IFTYPE_P2P_DEVICE)) {
1584                 if (IWL_MVM_TOF_IS_RESPONDER && vif->type == NL80211_IFTYPE_AP)
1585                         MVM_DEBUGFS_ADD_FILE_VIF(tof_responder_params,
1586                                                  mvmvif->dbgfs_dir,
1587                                                  S_IRUSR | S_IWUSR);
1588
1589                 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_request, mvmvif->dbgfs_dir,
1590                                          S_IRUSR | S_IWUSR);
1591                 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_req_ext, mvmvif->dbgfs_dir,
1592                                          S_IRUSR | S_IWUSR);
1593                 MVM_DEBUGFS_ADD_FILE_VIF(tof_enable, mvmvif->dbgfs_dir,
1594                                          S_IRUSR | S_IWUSR);
1595                 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_abort, mvmvif->dbgfs_dir,
1596                                          S_IRUSR | S_IWUSR);
1597                 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_response, mvmvif->dbgfs_dir,
1598                                          S_IRUSR);
1599         }
1600
1601         /*
1602          * Create symlink for convenience pointing to interface specific
1603          * debugfs entries for the driver. For example, under
1604          * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1605          * find
1606          * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1607          */
1608         snprintf(buf, 100, "../../../%s/%s/%s/%s",
1609                  dbgfs_dir->d_parent->d_parent->d_name.name,
1610                  dbgfs_dir->d_parent->d_name.name,
1611                  dbgfs_dir->d_name.name,
1612                  mvmvif->dbgfs_dir->d_name.name);
1613
1614         mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
1615                                                      mvm->debugfs_dir, buf);
1616         if (!mvmvif->dbgfs_slink)
1617                 IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
1618                         dbgfs_dir->d_name.name);
1619         return;
1620 err:
1621         IWL_ERR(mvm, "Can't create debugfs entity\n");
1622 }
1623
1624 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1625 {
1626         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1627
1628         debugfs_remove(mvmvif->dbgfs_slink);
1629         mvmvif->dbgfs_slink = NULL;
1630
1631         debugfs_remove_recursive(mvmvif->dbgfs_dir);
1632         mvmvif->dbgfs_dir = NULL;
1633 }