]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
Merge tag 'nfc-next-4.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo...
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / wireless / intel / iwlwifi / mvm / debugfs-vif.c
CommitLineData
820a1a50
JB
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 *
51368bf7 8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
25870cb7 9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
b525d081 10 * Copyright(c) 2016 Intel Deutschland GmbH
820a1a50
JB
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:
cb2f8277 30 * Intel Linux Wireless <linuxwifi@intel.com>
820a1a50
JB
31 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
32 *
33 * BSD LICENSE
34 *
51368bf7 35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
25870cb7 36 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
b525d081 37 * Copyright(c) 2016 Intel Deutschland GmbH
820a1a50
JB
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"
ce792918 68#include "fw-api-tof.h"
820a1a50
JB
69#include "debugfs.h"
70
e45a941d
AB
71static 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: {
717e2390 82 int dtimper = vif->bss_conf.dtim_period ?: 1;
e45a941d
AB
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;
e45a941d
AB
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;
84fd7608
EP
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;
e45a941d
AB
130 }
131}
132
133static 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;
e45a941d
AB
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;
84fd7608
EP
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;
e45a941d
AB
184 } else {
185 return -EINVAL;
186 }
187
188 mutex_lock(&mvm->mutex);
189 iwl_dbgfs_update_pm(mvm, vif, param, val);
999609f1 190 ret = iwl_mvm_power_update_mac(mvm);
e45a941d
AB
191 mutex_unlock(&mvm->mutex);
192
193 return ret ?: count;
194}
195
25870cb7
MG
196static 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
e45a941d
AB
211static 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
c1cb92fc 222 pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
e45a941d
AB
223
224 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
225}
226
820a1a50
JB
227static 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);
7f09d704 233 struct iwl_mvm *mvm = mvmvif->mvm;
820a1a50
JB
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
2284b951
EG
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
820a1a50
JB
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;
820a1a50
JB
285
286 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
287 lockdep_is_held(&mvm->mutex));
1ddbbb0c 288 if (!IS_ERR_OR_NULL(sta)) {
9d8ce6af 289 struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
1ddbbb0c
JB
290
291 pos += scnprintf(buf+pos, bufsz-pos,
1fa477c6 292 "ap_sta_id %d - reduced Tx power %d\n",
1ddbbb0c 293 ap_sta_id,
1fa477c6 294 mvm_sta->bt_reduced_txpower);
1ddbbb0c 295 }
820a1a50
JB
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
e45a941d
AB
312static 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
357static 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)
a1022927 446 ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
e45a941d 447 else
a1022927 448 ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
e45a941d
AB
449 mutex_unlock(&mvm->mutex);
450
451 return ret ?: count;
452}
453
454static 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
ce792918
GG
503static 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
510static 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;
e6c21be6
JB
516 u32 value;
517 int ret = -EINVAL;
ce792918
GG
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
563out:
564 mutex_unlock(&mvm->mutex);
565
566 return ret ?: count;
567}
568
569static 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
599static 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;
e6c21be6
JB
605 u32 value;
606 int ret = 0;
ce792918
GG
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
c84af35d 720 data = iwl_dbgfs_is_match("center_freq=", buf);
ce792918 721 if (data) {
c84af35d
AK
722 struct iwl_tof_responder_config_cmd *cmd =
723 &mvm->tof_data.responder_cfg;
724
ce792918 725 ret = kstrtou32(data, 10, &value);
c84af35d 726 if (ret == 0 && value) {
57fbcce3
JB
727 enum nl80211_band band = (cmd->channel_num <= 14) ?
728 NL80211_BAND_2GHZ :
729 NL80211_BAND_5GHZ;
c84af35d
AK
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 }
ce792918
GG
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
780out:
781 mutex_unlock(&mvm->mutex);
782
783 return ret ?: count;
784}
785
786static 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
842static 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;
e6c21be6
JB
848 u32 value;
849 int ret = 0;
ce792918
GG
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);
5ac15be8 919 goto out;
ce792918
GG
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);
5ac15be8 931 goto out;
ce792918
GG
932 }
933
934 data = iwl_dbgfs_is_match("ap=", buf);
935 if (data) {
5ac15be8 936 struct iwl_tof_range_req_ap_entry ap = {};
ce792918
GG
937 int size = sizeof(struct iwl_tof_range_req_ap_entry);
938 u16 burst_period;
939 u8 *mac = ap.bssid;
5b9d47cd 940 unsigned int i;
ce792918 941
3e0fa505 942 if (sscanf(data, "%u %hhd %hhd %hhd"
ce792918 943 "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
3e0fa505
AK
944 "%hhd %hhd %hd"
945 "%hhd %hhd %d"
946 "%hhx %hhd %hhd %hhd",
ce792918
GG
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 }
5b9d47cd 958 if (i >= IWL_MVM_TOF_MAX_APS) {
ce792918
GG
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);
5ac15be8 973 if (ret == 0 && value)
ce792918 974 ret = iwl_mvm_tof_range_request_cmd(mvm, vif);
5ac15be8 975 goto out;
ce792918
GG
976 }
977
5ac15be8 978 ret = -EINVAL;
ce792918
GG
979out:
980 mutex_unlock(&mvm->mutex);
981 return ret ?: count;
982}
983
984static 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,
3e0fa505
AK
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",
ce792918
GG
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,
3e0fa505 1034 ap->tsf_delta_direction,
ce792918
GG
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
1044static 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;
e6c21be6
JB
1050 u32 value;
1051 int ret = 0;
ce792918
GG
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);
5ac15be8 1103 if (ret == 0 && value)
ce792918 1104 ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif);
5ac15be8 1105 goto out;
ce792918
GG
1106 }
1107
5ac15be8 1108 ret = -EINVAL;
ce792918
GG
1109out:
1110 mutex_unlock(&mvm->mutex);
1111 return ret ?: count;
1112}
1113
1114static 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,
3e0fa505 1131 "tsf_timer_offset_msec = %hd\n",
ce792918 1132 cmd->tsf_timer_offset_msec);
3e0fa505 1133 pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n",
ce792918
GG
1134 cmd->min_delta_ftm);
1135 pos += scnprintf(buf + pos, bufsz - pos,
3e0fa505 1136 "ftm_format_and_bw20M = %hhd\n",
ce792918
GG
1137 cmd->ftm_format_and_bw20M);
1138 pos += scnprintf(buf + pos, bufsz - pos,
3e0fa505 1139 "ftm_format_and_bw40M = %hhd\n",
ce792918
GG
1140 cmd->ftm_format_and_bw40M);
1141 pos += scnprintf(buf + pos, bufsz - pos,
3e0fa505 1142 "ftm_format_and_bw80M = %hhd\n",
ce792918
GG
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
1149static 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;
e6c21be6
JB
1155 u32 value;
1156 int abort_id, ret = 0;
ce792918
GG
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
1179out:
1180 mutex_unlock(&mvm->mutex);
1181 return ret ?: count;
1182}
1183
1184static 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
1205static 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,
3e0fa505
AK
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",
ce792918
GG
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
a21d7bcb
JB
1255static 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;
b525d081 1260 bool prev;
a21d7bcb
JB
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);
b525d081
JB
1271 prev = iwl_mvm_vif_low_latency(mvmvif);
1272 mvmvif->low_latency_dbgfs = value;
1273 iwl_mvm_update_low_latency(mvm, vif, prev);
a21d7bcb
JB
1274 mutex_unlock(&mvm->mutex);
1275
1276 return count;
1277}
1278
1279static 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);
b525d081
JB
1285 char buf[30] = {};
1286 int len;
a21d7bcb 1287
b525d081
JB
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);
a21d7bcb
JB
1294}
1295
e39c1b5f
JB
1296static 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
1309static 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
ddf89ab1
EG
1324static 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
1362static 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
a80c1cf9
JB
1375static 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
1385static 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
1414static 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
dedfc0f3
AE
1428static 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
1437static 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
1468static 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
e45a941d
AB
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)
820a1a50
JB
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
1521MVM_DEBUGFS_READ_FILE_OPS(mac_params);
25870cb7 1522MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
e45a941d
AB
1523MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
1524MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
a21d7bcb 1525MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
e39c1b5f 1526MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
ddf89ab1 1527MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
ce792918
GG
1528MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable, 32);
1529MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request, 512);
1530MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32);
1531MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32);
1532MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
1533MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
a80c1cf9 1534MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
dedfc0f3 1535MVM_DEBUGFS_WRITE_FILE_OPS(lqm_send_cmd, 64);
820a1a50
JB
1536
1537void 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);
820a1a50
JB
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
ad2549d8 1558 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
e45a941d
AB
1559 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
1560 (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
7303dd7f 1561 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
e45a941d
AB
1562 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
1563 S_IRUSR);
1564
25870cb7 1565 MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, S_IRUSR);
32a65c34 1566 MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR);
a21d7bcb
JB
1567 MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir,
1568 S_IRUSR | S_IWUSR);
e39c1b5f
JB
1569 MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir,
1570 S_IRUSR | S_IWUSR);
ddf89ab1
EG
1571 MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir,
1572 S_IRUSR | S_IWUSR);
a80c1cf9
JB
1573 MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir,
1574 S_IRUSR | S_IWUSR);
dedfc0f3 1575 MVM_DEBUGFS_ADD_FILE_VIF(lqm_send_cmd, mvmvif->dbgfs_dir, S_IWUSR);
820a1a50 1576
e45a941d
AB
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
ce792918
GG
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
820a1a50
JB
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;
1620err:
1621 IWL_ERR(mvm, "Can't create debugfs entity\n");
1622}
1623
1624void 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}