blob: 1aa6c7e930888e46593e95e4439b52c4ee370e14 [file] [log] [blame]
Johannes Berg820a1a52013-11-12 16:58:41 +01001/******************************************************************************
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 *
Emmanuel Grumbach51368bf2013-12-30 13:15:54 +02008 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
Matti Gottlieb25870cb2015-05-04 09:34:37 +03009 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
Johannes Berg40e86a32017-04-19 09:58:50 +020010 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
Johannes Berg820a1a52013-11-12 16:58:41 +010011 *
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 *
Johannes Berg820a1a52013-11-12 16:58:41 +010021 * The full GNU General Public License is included in this distribution
22 * in the file called COPYING.
23 *
24 * Contact Information:
Emmanuel Grumbachcb2f8272015-11-17 15:39:56 +020025 * Intel Linux Wireless <linuxwifi@intel.com>
Johannes Berg820a1a52013-11-12 16:58:41 +010026 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *
28 * BSD LICENSE
29 *
Emmanuel Grumbach51368bf2013-12-30 13:15:54 +020030 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
Matti Gottlieb25870cb2015-05-04 09:34:37 +030031 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
Johannes Berg40e86a32017-04-19 09:58:50 +020032 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
Johannes Berg820a1a52013-11-12 16:58:41 +010033 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 *
39 * * Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * * Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in
43 * the documentation and/or other materials provided with the
44 * distribution.
45 * * Neither the name Intel Corporation nor the names of its
46 * contributors may be used to endorse or promote products derived
47 * from this software without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
52 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
53 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 *
61 *****************************************************************************/
62#include "mvm.h"
Johannes Bergd172a5e2017-06-02 15:15:53 +020063#include "fw/api/tof.h"
Johannes Berg820a1a52013-11-12 16:58:41 +010064#include "debugfs.h"
65
Alexander Bondare45a9412013-12-04 10:13:24 +020066static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
67 struct ieee80211_vif *vif,
68 enum iwl_dbgfs_pm_mask param, int val)
69{
70 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
71 struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
72
73 dbgfs_pm->mask |= param;
74
75 switch (param) {
76 case MVM_DEBUGFS_PM_KEEP_ALIVE: {
Emmanuel Grumbach717e2392014-07-31 14:39:40 +030077 int dtimper = vif->bss_conf.dtim_period ?: 1;
Alexander Bondare45a9412013-12-04 10:13:24 +020078 int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
79
80 IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
81 if (val * MSEC_PER_SEC < 3 * dtimper_msec)
82 IWL_WARN(mvm,
83 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
84 val * MSEC_PER_SEC, 3 * dtimper_msec);
85 dbgfs_pm->keep_alive_seconds = val;
86 break;
87 }
88 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
89 IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
90 val ? "enabled" : "disabled");
91 dbgfs_pm->skip_over_dtim = val;
92 break;
93 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
94 IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
95 dbgfs_pm->skip_dtim_periods = val;
96 break;
97 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
98 IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
99 dbgfs_pm->rx_data_timeout = val;
100 break;
101 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
102 IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
103 dbgfs_pm->tx_data_timeout = val;
104 break;
Alexander Bondare45a9412013-12-04 10:13:24 +0200105 case MVM_DEBUGFS_PM_LPRX_ENA:
106 IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
107 dbgfs_pm->lprx_ena = val;
108 break;
109 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
110 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
111 dbgfs_pm->lprx_rssi_threshold = val;
112 break;
113 case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
114 IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
115 dbgfs_pm->snooze_ena = val;
116 break;
117 case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING:
118 IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val);
119 dbgfs_pm->uapsd_misbehaving = val;
120 break;
Eliad Peller84fd7602014-07-30 15:42:19 +0300121 case MVM_DEBUGFS_PM_USE_PS_POLL:
122 IWL_DEBUG_POWER(mvm, "use_ps_poll=%d\n", val);
123 dbgfs_pm->use_ps_poll = val;
124 break;
Alexander Bondare45a9412013-12-04 10:13:24 +0200125 }
126}
127
128static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
129 size_t count, loff_t *ppos)
130{
131 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
132 struct iwl_mvm *mvm = mvmvif->mvm;
133 enum iwl_dbgfs_pm_mask param;
134 int val, ret;
135
136 if (!strncmp("keep_alive=", buf, 11)) {
137 if (sscanf(buf + 11, "%d", &val) != 1)
138 return -EINVAL;
139 param = MVM_DEBUGFS_PM_KEEP_ALIVE;
140 } else if (!strncmp("skip_over_dtim=", buf, 15)) {
141 if (sscanf(buf + 15, "%d", &val) != 1)
142 return -EINVAL;
143 param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
144 } else if (!strncmp("skip_dtim_periods=", buf, 18)) {
145 if (sscanf(buf + 18, "%d", &val) != 1)
146 return -EINVAL;
147 param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
148 } else if (!strncmp("rx_data_timeout=", buf, 16)) {
149 if (sscanf(buf + 16, "%d", &val) != 1)
150 return -EINVAL;
151 param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
152 } else if (!strncmp("tx_data_timeout=", buf, 16)) {
153 if (sscanf(buf + 16, "%d", &val) != 1)
154 return -EINVAL;
155 param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
Alexander Bondare45a9412013-12-04 10:13:24 +0200156 } else if (!strncmp("lprx=", buf, 5)) {
157 if (sscanf(buf + 5, "%d", &val) != 1)
158 return -EINVAL;
159 param = MVM_DEBUGFS_PM_LPRX_ENA;
160 } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
161 if (sscanf(buf + 20, "%d", &val) != 1)
162 return -EINVAL;
163 if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
164 POWER_LPRX_RSSI_THRESHOLD_MIN)
165 return -EINVAL;
166 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
167 } else if (!strncmp("snooze_enable=", buf, 14)) {
168 if (sscanf(buf + 14, "%d", &val) != 1)
169 return -EINVAL;
170 param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
171 } else if (!strncmp("uapsd_misbehaving=", buf, 18)) {
172 if (sscanf(buf + 18, "%d", &val) != 1)
173 return -EINVAL;
174 param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING;
Eliad Peller84fd7602014-07-30 15:42:19 +0300175 } else if (!strncmp("use_ps_poll=", buf, 12)) {
176 if (sscanf(buf + 12, "%d", &val) != 1)
177 return -EINVAL;
178 param = MVM_DEBUGFS_PM_USE_PS_POLL;
Alexander Bondare45a9412013-12-04 10:13:24 +0200179 } else {
180 return -EINVAL;
181 }
182
183 mutex_lock(&mvm->mutex);
184 iwl_dbgfs_update_pm(mvm, vif, param, val);
Arik Nemtsov999609f2014-05-15 17:31:51 +0300185 ret = iwl_mvm_power_update_mac(mvm);
Alexander Bondare45a9412013-12-04 10:13:24 +0200186 mutex_unlock(&mvm->mutex);
187
188 return ret ?: count;
189}
190
Matti Gottlieb25870cb2015-05-04 09:34:37 +0300191static ssize_t iwl_dbgfs_tx_pwr_lmt_read(struct file *file,
192 char __user *user_buf,
193 size_t count, loff_t *ppos)
194{
195 struct ieee80211_vif *vif = file->private_data;
196 char buf[64];
197 int bufsz = sizeof(buf);
198 int pos;
199
200 pos = scnprintf(buf, bufsz, "bss limit = %d\n",
201 vif->bss_conf.txpower);
202
203 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
204}
205
Alexander Bondare45a9412013-12-04 10:13:24 +0200206static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
207 char __user *user_buf,
208 size_t count, loff_t *ppos)
209{
210 struct ieee80211_vif *vif = file->private_data;
211 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
212 struct iwl_mvm *mvm = mvmvif->mvm;
213 char buf[512];
214 int bufsz = sizeof(buf);
215 int pos;
216
Emmanuel Grumbachc1cb92f2014-01-28 10:17:18 +0200217 pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
Alexander Bondare45a9412013-12-04 10:13:24 +0200218
219 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
220}
221
Johannes Berg820a1a52013-11-12 16:58:41 +0100222static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
223 char __user *user_buf,
224 size_t count, loff_t *ppos)
225{
226 struct ieee80211_vif *vif = file->private_data;
227 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
Johannes Berg7f09d702013-11-12 17:16:38 +0100228 struct iwl_mvm *mvm = mvmvif->mvm;
Johannes Berg820a1a52013-11-12 16:58:41 +0100229 u8 ap_sta_id;
230 struct ieee80211_chanctx_conf *chanctx_conf;
231 char buf[512];
232 int bufsz = sizeof(buf);
233 int pos = 0;
234 int i;
235
236 mutex_lock(&mvm->mutex);
237
238 ap_sta_id = mvmvif->ap_sta_id;
239
Emmanuel Grumbach2284b952014-01-15 16:57:03 +0200240 switch (ieee80211_vif_type_p2p(vif)) {
241 case NL80211_IFTYPE_ADHOC:
242 pos += scnprintf(buf+pos, bufsz-pos, "type: ibss\n");
243 break;
244 case NL80211_IFTYPE_STATION:
245 pos += scnprintf(buf+pos, bufsz-pos, "type: bss\n");
246 break;
247 case NL80211_IFTYPE_AP:
248 pos += scnprintf(buf+pos, bufsz-pos, "type: ap\n");
249 break;
250 case NL80211_IFTYPE_P2P_CLIENT:
251 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p client\n");
252 break;
253 case NL80211_IFTYPE_P2P_GO:
254 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p go\n");
255 break;
256 case NL80211_IFTYPE_P2P_DEVICE:
257 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p dev\n");
258 break;
259 default:
260 break;
261 }
262
Johannes Berg820a1a52013-11-12 16:58:41 +0100263 pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
264 mvmvif->id, mvmvif->color);
265 pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
266 vif->bss_conf.bssid);
Luca Coelho7d9d0d52018-04-12 16:15:07 +0300267 pos += scnprintf(buf+pos, bufsz-pos, "Load: %d\n",
268 mvm->tcm.result.load[mvmvif->id]);
Johannes Berg820a1a52013-11-12 16:58:41 +0100269 pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
270 for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
271 pos += scnprintf(buf+pos, bufsz-pos,
272 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
273 i, mvmvif->queue_params[i].txop,
274 mvmvif->queue_params[i].cw_min,
275 mvmvif->queue_params[i].cw_max,
276 mvmvif->queue_params[i].aifs,
277 mvmvif->queue_params[i].uapsd);
278
279 if (vif->type == NL80211_IFTYPE_STATION &&
Sara Sharon0ae98812017-01-04 14:53:58 +0200280 ap_sta_id != IWL_MVM_INVALID_STA) {
Sara Sharon13303c02016-04-10 15:51:54 +0300281 struct iwl_mvm_sta *mvm_sta;
Johannes Berg820a1a52013-11-12 16:58:41 +0100282
Sara Sharon13303c02016-04-10 15:51:54 +0300283 mvm_sta = iwl_mvm_sta_from_staid_protected(mvm, ap_sta_id);
284 if (mvm_sta) {
Johannes Berg1ddbbb02013-12-04 22:39:17 +0100285 pos += scnprintf(buf+pos, bufsz-pos,
Emmanuel Grumbach1fa477c2014-05-20 13:54:27 +0300286 "ap_sta_id %d - reduced Tx power %d\n",
Johannes Berg1ddbbb02013-12-04 22:39:17 +0100287 ap_sta_id,
Emmanuel Grumbach1fa477c2014-05-20 13:54:27 +0300288 mvm_sta->bt_reduced_txpower);
Johannes Berg1ddbbb02013-12-04 22:39:17 +0100289 }
Johannes Berg820a1a52013-11-12 16:58:41 +0100290 }
291
292 rcu_read_lock();
293 chanctx_conf = rcu_dereference(vif->chanctx_conf);
294 if (chanctx_conf)
295 pos += scnprintf(buf+pos, bufsz-pos,
296 "idle rx chains %d, active rx chains: %d\n",
297 chanctx_conf->rx_chains_static,
298 chanctx_conf->rx_chains_dynamic);
299 rcu_read_unlock();
300
301 mutex_unlock(&mvm->mutex);
302
303 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
304}
305
Alexander Bondare45a9412013-12-04 10:13:24 +0200306static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
307 enum iwl_dbgfs_bf_mask param, int value)
308{
309 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
310 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
311
312 dbgfs_bf->mask |= param;
313
314 switch (param) {
315 case MVM_DEBUGFS_BF_ENERGY_DELTA:
316 dbgfs_bf->bf_energy_delta = value;
317 break;
318 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
319 dbgfs_bf->bf_roaming_energy_delta = value;
320 break;
321 case MVM_DEBUGFS_BF_ROAMING_STATE:
322 dbgfs_bf->bf_roaming_state = value;
323 break;
324 case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
325 dbgfs_bf->bf_temp_threshold = value;
326 break;
327 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
328 dbgfs_bf->bf_temp_fast_filter = value;
329 break;
330 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
331 dbgfs_bf->bf_temp_slow_filter = value;
332 break;
333 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
334 dbgfs_bf->bf_enable_beacon_filter = value;
335 break;
336 case MVM_DEBUGFS_BF_DEBUG_FLAG:
337 dbgfs_bf->bf_debug_flag = value;
338 break;
339 case MVM_DEBUGFS_BF_ESCAPE_TIMER:
340 dbgfs_bf->bf_escape_timer = value;
341 break;
342 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
343 dbgfs_bf->ba_enable_beacon_abort = value;
344 break;
345 case MVM_DEBUGFS_BA_ESCAPE_TIMER:
346 dbgfs_bf->ba_escape_timer = value;
347 break;
348 }
349}
350
351static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
352 size_t count, loff_t *ppos)
353{
354 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
355 struct iwl_mvm *mvm = mvmvif->mvm;
356 enum iwl_dbgfs_bf_mask param;
357 int value, ret = 0;
358
359 if (!strncmp("bf_energy_delta=", buf, 16)) {
360 if (sscanf(buf+16, "%d", &value) != 1)
361 return -EINVAL;
362 if (value < IWL_BF_ENERGY_DELTA_MIN ||
363 value > IWL_BF_ENERGY_DELTA_MAX)
364 return -EINVAL;
365 param = MVM_DEBUGFS_BF_ENERGY_DELTA;
366 } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
367 if (sscanf(buf+24, "%d", &value) != 1)
368 return -EINVAL;
369 if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
370 value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
371 return -EINVAL;
372 param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
373 } else if (!strncmp("bf_roaming_state=", buf, 17)) {
374 if (sscanf(buf+17, "%d", &value) != 1)
375 return -EINVAL;
376 if (value < IWL_BF_ROAMING_STATE_MIN ||
377 value > IWL_BF_ROAMING_STATE_MAX)
378 return -EINVAL;
379 param = MVM_DEBUGFS_BF_ROAMING_STATE;
380 } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
381 if (sscanf(buf+18, "%d", &value) != 1)
382 return -EINVAL;
383 if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
384 value > IWL_BF_TEMP_THRESHOLD_MAX)
385 return -EINVAL;
386 param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
387 } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
388 if (sscanf(buf+20, "%d", &value) != 1)
389 return -EINVAL;
390 if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
391 value > IWL_BF_TEMP_FAST_FILTER_MAX)
392 return -EINVAL;
393 param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
394 } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
395 if (sscanf(buf+20, "%d", &value) != 1)
396 return -EINVAL;
397 if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
398 value > IWL_BF_TEMP_SLOW_FILTER_MAX)
399 return -EINVAL;
400 param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
401 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
402 if (sscanf(buf+24, "%d", &value) != 1)
403 return -EINVAL;
404 if (value < 0 || value > 1)
405 return -EINVAL;
406 param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
407 } else if (!strncmp("bf_debug_flag=", buf, 14)) {
408 if (sscanf(buf+14, "%d", &value) != 1)
409 return -EINVAL;
410 if (value < 0 || value > 1)
411 return -EINVAL;
412 param = MVM_DEBUGFS_BF_DEBUG_FLAG;
413 } else if (!strncmp("bf_escape_timer=", buf, 16)) {
414 if (sscanf(buf+16, "%d", &value) != 1)
415 return -EINVAL;
416 if (value < IWL_BF_ESCAPE_TIMER_MIN ||
417 value > IWL_BF_ESCAPE_TIMER_MAX)
418 return -EINVAL;
419 param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
420 } else if (!strncmp("ba_escape_timer=", buf, 16)) {
421 if (sscanf(buf+16, "%d", &value) != 1)
422 return -EINVAL;
423 if (value < IWL_BA_ESCAPE_TIMER_MIN ||
424 value > IWL_BA_ESCAPE_TIMER_MAX)
425 return -EINVAL;
426 param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
427 } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
428 if (sscanf(buf+23, "%d", &value) != 1)
429 return -EINVAL;
430 if (value < 0 || value > 1)
431 return -EINVAL;
432 param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
433 } else {
434 return -EINVAL;
435 }
436
437 mutex_lock(&mvm->mutex);
438 iwl_dbgfs_update_bf(vif, param, value);
439 if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
Emmanuel Grumbacha1022922014-05-12 11:36:41 +0300440 ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
Alexander Bondare45a9412013-12-04 10:13:24 +0200441 else
Emmanuel Grumbacha1022922014-05-12 11:36:41 +0300442 ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
Alexander Bondare45a9412013-12-04 10:13:24 +0200443 mutex_unlock(&mvm->mutex);
444
445 return ret ?: count;
446}
447
448static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
449 char __user *user_buf,
450 size_t count, loff_t *ppos)
451{
452 struct ieee80211_vif *vif = file->private_data;
453 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
454 char buf[256];
455 int pos = 0;
456 const size_t bufsz = sizeof(buf);
457 struct iwl_beacon_filter_cmd cmd = {
458 IWL_BF_CMD_CONFIG_DEFAULTS,
459 .bf_enable_beacon_filter =
460 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
461 .ba_enable_beacon_abort =
462 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
463 };
464
465 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
466 if (mvmvif->bf_data.bf_enabled)
467 cmd.bf_enable_beacon_filter = cpu_to_le32(1);
468 else
469 cmd.bf_enable_beacon_filter = 0;
470
471 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
472 le32_to_cpu(cmd.bf_energy_delta));
473 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
474 le32_to_cpu(cmd.bf_roaming_energy_delta));
475 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
476 le32_to_cpu(cmd.bf_roaming_state));
477 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
478 le32_to_cpu(cmd.bf_temp_threshold));
479 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
480 le32_to_cpu(cmd.bf_temp_fast_filter));
481 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
482 le32_to_cpu(cmd.bf_temp_slow_filter));
483 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
484 le32_to_cpu(cmd.bf_enable_beacon_filter));
485 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
486 le32_to_cpu(cmd.bf_debug_flag));
487 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
488 le32_to_cpu(cmd.bf_escape_timer));
489 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
490 le32_to_cpu(cmd.ba_escape_timer));
491 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
492 le32_to_cpu(cmd.ba_enable_beacon_abort));
493
494 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
495}
496
Gregory Greenmance792912015-06-02 18:06:16 +0300497static inline char *iwl_dbgfs_is_match(char *name, char *buf)
498{
499 int len = strlen(name);
500
501 return !strncmp(name, buf, len) ? buf + len : NULL;
502}
503
Roee Zamirb3bee582016-08-02 13:55:13 +0300504static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file,
505 char __user *user_buf,
506 size_t count, loff_t *ppos)
507{
508 struct ieee80211_vif *vif = file->private_data;
509 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
510 struct iwl_mvm *mvm = mvmvif->mvm;
511 u32 curr_gp2;
512 u64 curr_os;
513 s64 diff;
514 char buf[64];
515 const size_t bufsz = sizeof(buf);
516 int pos = 0;
517
518 iwl_mvm_get_sync_time(mvm, &curr_gp2, &curr_os);
519 do_div(curr_os, NSEC_PER_USEC);
520 diff = curr_os - curr_gp2;
521 pos += scnprintf(buf + pos, bufsz - pos, "diff=%lld\n", diff);
522
523 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
524}
525
Gregory Greenmance792912015-06-02 18:06:16 +0300526static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif,
527 char *buf,
528 size_t count, loff_t *ppos)
529{
530 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
531 struct iwl_mvm *mvm = mvmvif->mvm;
Johannes Berge6c21be2015-09-24 22:15:02 +0200532 u32 value;
533 int ret = -EINVAL;
Gregory Greenmance792912015-06-02 18:06:16 +0300534 char *data;
535
536 mutex_lock(&mvm->mutex);
537
538 data = iwl_dbgfs_is_match("tof_disabled=", buf);
539 if (data) {
540 ret = kstrtou32(data, 10, &value);
541 if (ret == 0)
542 mvm->tof_data.tof_cfg.tof_disabled = value;
543 goto out;
544 }
545
546 data = iwl_dbgfs_is_match("one_sided_disabled=", buf);
547 if (data) {
548 ret = kstrtou32(data, 10, &value);
549 if (ret == 0)
550 mvm->tof_data.tof_cfg.one_sided_disabled = value;
551 goto out;
552 }
553
554 data = iwl_dbgfs_is_match("is_debug_mode=", buf);
555 if (data) {
556 ret = kstrtou32(data, 10, &value);
557 if (ret == 0)
558 mvm->tof_data.tof_cfg.is_debug_mode = value;
559 goto out;
560 }
561
562 data = iwl_dbgfs_is_match("is_buf=", buf);
563 if (data) {
564 ret = kstrtou32(data, 10, &value);
565 if (ret == 0)
566 mvm->tof_data.tof_cfg.is_buf_required = value;
567 goto out;
568 }
569
570 data = iwl_dbgfs_is_match("send_tof_cfg=", buf);
571 if (data) {
572 ret = kstrtou32(data, 10, &value);
573 if (ret == 0 && value) {
574 ret = iwl_mvm_tof_config_cmd(mvm);
575 goto out;
576 }
577 }
578
579out:
580 mutex_unlock(&mvm->mutex);
581
582 return ret ?: count;
583}
584
585static ssize_t iwl_dbgfs_tof_enable_read(struct file *file,
586 char __user *user_buf,
587 size_t count, loff_t *ppos)
588{
589 struct ieee80211_vif *vif = file->private_data;
590 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
591 struct iwl_mvm *mvm = mvmvif->mvm;
592 char buf[256];
593 int pos = 0;
594 const size_t bufsz = sizeof(buf);
595 struct iwl_tof_config_cmd *cmd;
596
597 cmd = &mvm->tof_data.tof_cfg;
598
599 mutex_lock(&mvm->mutex);
600
601 pos += scnprintf(buf + pos, bufsz - pos, "tof_disabled = %d\n",
602 cmd->tof_disabled);
603 pos += scnprintf(buf + pos, bufsz - pos, "one_sided_disabled = %d\n",
604 cmd->one_sided_disabled);
605 pos += scnprintf(buf + pos, bufsz - pos, "is_debug_mode = %d\n",
606 cmd->is_debug_mode);
607 pos += scnprintf(buf + pos, bufsz - pos, "is_buf_required = %d\n",
608 cmd->is_buf_required);
609
610 mutex_unlock(&mvm->mutex);
611
612 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
613}
614
615static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif,
616 char *buf,
617 size_t count, loff_t *ppos)
618{
619 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
620 struct iwl_mvm *mvm = mvmvif->mvm;
Johannes Berge6c21be2015-09-24 22:15:02 +0200621 u32 value;
622 int ret = 0;
Gregory Greenmance792912015-06-02 18:06:16 +0300623 char *data;
624
625 mutex_lock(&mvm->mutex);
626
627 data = iwl_dbgfs_is_match("burst_period=", buf);
628 if (data) {
629 ret = kstrtou32(data, 10, &value);
630 if (!ret)
631 mvm->tof_data.responder_cfg.burst_period =
632 cpu_to_le16(value);
633 goto out;
634 }
635
636 data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
637 if (data) {
638 ret = kstrtou32(data, 10, &value);
639 if (ret == 0)
640 mvm->tof_data.responder_cfg.min_delta_ftm = value;
641 goto out;
642 }
643
644 data = iwl_dbgfs_is_match("burst_duration=", buf);
645 if (data) {
646 ret = kstrtou32(data, 10, &value);
647 if (ret == 0)
648 mvm->tof_data.responder_cfg.burst_duration = value;
649 goto out;
650 }
651
652 data = iwl_dbgfs_is_match("num_of_burst_exp=", buf);
653 if (data) {
654 ret = kstrtou32(data, 10, &value);
655 if (ret == 0)
656 mvm->tof_data.responder_cfg.num_of_burst_exp = value;
657 goto out;
658 }
659
660 data = iwl_dbgfs_is_match("abort_responder=", buf);
661 if (data) {
662 ret = kstrtou32(data, 10, &value);
663 if (ret == 0)
664 mvm->tof_data.responder_cfg.abort_responder = value;
665 goto out;
666 }
667
668 data = iwl_dbgfs_is_match("get_ch_est=", buf);
669 if (data) {
670 ret = kstrtou32(data, 10, &value);
671 if (ret == 0)
672 mvm->tof_data.responder_cfg.get_ch_est = value;
673 goto out;
674 }
675
676 data = iwl_dbgfs_is_match("recv_sta_req_params=", buf);
677 if (data) {
678 ret = kstrtou32(data, 10, &value);
679 if (ret == 0)
680 mvm->tof_data.responder_cfg.recv_sta_req_params = value;
681 goto out;
682 }
683
684 data = iwl_dbgfs_is_match("channel_num=", buf);
685 if (data) {
686 ret = kstrtou32(data, 10, &value);
687 if (ret == 0)
688 mvm->tof_data.responder_cfg.channel_num = value;
689 goto out;
690 }
691
692 data = iwl_dbgfs_is_match("bandwidth=", buf);
693 if (data) {
694 ret = kstrtou32(data, 10, &value);
695 if (ret == 0)
696 mvm->tof_data.responder_cfg.bandwidth = value;
697 goto out;
698 }
699
700 data = iwl_dbgfs_is_match("rate=", buf);
701 if (data) {
702 ret = kstrtou32(data, 10, &value);
703 if (ret == 0)
704 mvm->tof_data.responder_cfg.rate = value;
705 goto out;
706 }
707
708 data = iwl_dbgfs_is_match("bssid=", buf);
709 if (data) {
710 u8 *mac = mvm->tof_data.responder_cfg.bssid;
711
712 if (!mac_pton(data, mac)) {
713 ret = -EINVAL;
714 goto out;
715 }
716 }
717
718 data = iwl_dbgfs_is_match("tsf_timer_offset_msecs=", buf);
719 if (data) {
720 ret = kstrtou32(data, 10, &value);
721 if (ret == 0)
722 mvm->tof_data.responder_cfg.tsf_timer_offset_msecs =
723 cpu_to_le16(value);
724 goto out;
725 }
726
727 data = iwl_dbgfs_is_match("toa_offset=", buf);
728 if (data) {
729 ret = kstrtou32(data, 10, &value);
730 if (ret == 0)
731 mvm->tof_data.responder_cfg.toa_offset =
732 cpu_to_le16(value);
733 goto out;
734 }
735
Assaf Kraussc84af352015-08-12 17:52:12 +0300736 data = iwl_dbgfs_is_match("center_freq=", buf);
Gregory Greenmance792912015-06-02 18:06:16 +0300737 if (data) {
Assaf Kraussc84af352015-08-12 17:52:12 +0300738 struct iwl_tof_responder_config_cmd *cmd =
739 &mvm->tof_data.responder_cfg;
740
Gregory Greenmance792912015-06-02 18:06:16 +0300741 ret = kstrtou32(data, 10, &value);
Assaf Kraussc84af352015-08-12 17:52:12 +0300742 if (ret == 0 && value) {
Johannes Berg57fbcce2016-04-12 15:56:15 +0200743 enum nl80211_band band = (cmd->channel_num <= 14) ?
744 NL80211_BAND_2GHZ :
745 NL80211_BAND_5GHZ;
Assaf Kraussc84af352015-08-12 17:52:12 +0300746 struct ieee80211_channel chn = {
747 .band = band,
748 .center_freq = ieee80211_channel_to_frequency(
749 cmd->channel_num, band),
750 };
751 struct cfg80211_chan_def chandef = {
752 .chan = &chn,
753 .center_freq1 =
754 ieee80211_channel_to_frequency(value,
755 band),
756 };
757
758 cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef);
759 }
Gregory Greenmance792912015-06-02 18:06:16 +0300760 goto out;
761 }
762
763 data = iwl_dbgfs_is_match("ftm_per_burst=", buf);
764 if (data) {
765 ret = kstrtou32(data, 10, &value);
766 if (ret == 0)
767 mvm->tof_data.responder_cfg.ftm_per_burst = value;
768 goto out;
769 }
770
771 data = iwl_dbgfs_is_match("ftm_resp_ts_avail=", buf);
772 if (data) {
773 ret = kstrtou32(data, 10, &value);
774 if (ret == 0)
775 mvm->tof_data.responder_cfg.ftm_resp_ts_avail = value;
776 goto out;
777 }
778
779 data = iwl_dbgfs_is_match("asap_mode=", buf);
780 if (data) {
781 ret = kstrtou32(data, 10, &value);
782 if (ret == 0)
783 mvm->tof_data.responder_cfg.asap_mode = value;
784 goto out;
785 }
786
787 data = iwl_dbgfs_is_match("send_responder_cfg=", buf);
788 if (data) {
789 ret = kstrtou32(data, 10, &value);
790 if (ret == 0 && value) {
791 ret = iwl_mvm_tof_responder_cmd(mvm, vif);
792 goto out;
793 }
794 }
795
796out:
797 mutex_unlock(&mvm->mutex);
798
799 return ret ?: count;
800}
801
802static ssize_t iwl_dbgfs_tof_responder_params_read(struct file *file,
803 char __user *user_buf,
804 size_t count, loff_t *ppos)
805{
806 struct ieee80211_vif *vif = file->private_data;
807 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
808 struct iwl_mvm *mvm = mvmvif->mvm;
809 char buf[256];
810 int pos = 0;
811 const size_t bufsz = sizeof(buf);
812 struct iwl_tof_responder_config_cmd *cmd;
813
814 cmd = &mvm->tof_data.responder_cfg;
815
816 mutex_lock(&mvm->mutex);
817
818 pos += scnprintf(buf + pos, bufsz - pos, "burst_period = %d\n",
819 le16_to_cpu(cmd->burst_period));
820 pos += scnprintf(buf + pos, bufsz - pos, "burst_duration = %d\n",
821 cmd->burst_duration);
822 pos += scnprintf(buf + pos, bufsz - pos, "bandwidth = %d\n",
823 cmd->bandwidth);
824 pos += scnprintf(buf + pos, bufsz - pos, "channel_num = %d\n",
825 cmd->channel_num);
826 pos += scnprintf(buf + pos, bufsz - pos, "ctrl_ch_position = 0x%x\n",
827 cmd->ctrl_ch_position);
828 pos += scnprintf(buf + pos, bufsz - pos, "bssid = %pM\n",
829 cmd->bssid);
830 pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %d\n",
831 cmd->min_delta_ftm);
832 pos += scnprintf(buf + pos, bufsz - pos, "num_of_burst_exp = %d\n",
833 cmd->num_of_burst_exp);
834 pos += scnprintf(buf + pos, bufsz - pos, "rate = %d\n", cmd->rate);
835 pos += scnprintf(buf + pos, bufsz - pos, "abort_responder = %d\n",
836 cmd->abort_responder);
837 pos += scnprintf(buf + pos, bufsz - pos, "get_ch_est = %d\n",
838 cmd->get_ch_est);
839 pos += scnprintf(buf + pos, bufsz - pos, "recv_sta_req_params = %d\n",
840 cmd->recv_sta_req_params);
841 pos += scnprintf(buf + pos, bufsz - pos, "ftm_per_burst = %d\n",
842 cmd->ftm_per_burst);
843 pos += scnprintf(buf + pos, bufsz - pos, "ftm_resp_ts_avail = %d\n",
844 cmd->ftm_resp_ts_avail);
845 pos += scnprintf(buf + pos, bufsz - pos, "asap_mode = %d\n",
846 cmd->asap_mode);
847 pos += scnprintf(buf + pos, bufsz - pos,
848 "tsf_timer_offset_msecs = %d\n",
849 le16_to_cpu(cmd->tsf_timer_offset_msecs));
850 pos += scnprintf(buf + pos, bufsz - pos, "toa_offset = %d\n",
851 le16_to_cpu(cmd->toa_offset));
852
853 mutex_unlock(&mvm->mutex);
854
855 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
856}
857
858static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
859 char *buf, size_t count,
860 loff_t *ppos)
861{
862 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
863 struct iwl_mvm *mvm = mvmvif->mvm;
Johannes Berge6c21be2015-09-24 22:15:02 +0200864 u32 value;
865 int ret = 0;
Gregory Greenmance792912015-06-02 18:06:16 +0300866 char *data;
867
868 mutex_lock(&mvm->mutex);
869
870 data = iwl_dbgfs_is_match("request_id=", buf);
871 if (data) {
872 ret = kstrtou32(data, 10, &value);
873 if (ret == 0)
874 mvm->tof_data.range_req.request_id = value;
875 goto out;
876 }
877
878 data = iwl_dbgfs_is_match("initiator=", buf);
879 if (data) {
880 ret = kstrtou32(data, 10, &value);
881 if (ret == 0)
882 mvm->tof_data.range_req.initiator = value;
883 goto out;
884 }
885
886 data = iwl_dbgfs_is_match("one_sided_los_disable=", buf);
887 if (data) {
888 ret = kstrtou32(data, 10, &value);
889 if (ret == 0)
890 mvm->tof_data.range_req.one_sided_los_disable = value;
891 goto out;
892 }
893
894 data = iwl_dbgfs_is_match("req_timeout=", buf);
895 if (data) {
896 ret = kstrtou32(data, 10, &value);
897 if (ret == 0)
898 mvm->tof_data.range_req.req_timeout = value;
899 goto out;
900 }
901
902 data = iwl_dbgfs_is_match("report_policy=", buf);
903 if (data) {
904 ret = kstrtou32(data, 10, &value);
905 if (ret == 0)
906 mvm->tof_data.range_req.report_policy = value;
907 goto out;
908 }
909
910 data = iwl_dbgfs_is_match("macaddr_random=", buf);
911 if (data) {
912 ret = kstrtou32(data, 10, &value);
913 if (ret == 0)
914 mvm->tof_data.range_req.macaddr_random = value;
915 goto out;
916 }
917
918 data = iwl_dbgfs_is_match("num_of_ap=", buf);
919 if (data) {
920 ret = kstrtou32(data, 10, &value);
921 if (ret == 0)
922 mvm->tof_data.range_req.num_of_ap = value;
923 goto out;
924 }
925
926 data = iwl_dbgfs_is_match("macaddr_template=", buf);
927 if (data) {
928 u8 mac[ETH_ALEN];
929
930 if (!mac_pton(data, mac)) {
931 ret = -EINVAL;
932 goto out;
933 }
934 memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN);
Assaf Krauss5ac15be2015-09-16 11:47:14 +0300935 goto out;
Gregory Greenmance792912015-06-02 18:06:16 +0300936 }
937
938 data = iwl_dbgfs_is_match("macaddr_mask=", buf);
939 if (data) {
940 u8 mac[ETH_ALEN];
941
942 if (!mac_pton(data, mac)) {
943 ret = -EINVAL;
944 goto out;
945 }
946 memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN);
Assaf Krauss5ac15be2015-09-16 11:47:14 +0300947 goto out;
Gregory Greenmance792912015-06-02 18:06:16 +0300948 }
949
950 data = iwl_dbgfs_is_match("ap=", buf);
951 if (data) {
Assaf Krauss5ac15be2015-09-16 11:47:14 +0300952 struct iwl_tof_range_req_ap_entry ap = {};
Gregory Greenmance792912015-06-02 18:06:16 +0300953 int size = sizeof(struct iwl_tof_range_req_ap_entry);
954 u16 burst_period;
955 u8 *mac = ap.bssid;
Dan Carpenter5b9d47c2015-08-11 00:45:03 +0300956 unsigned int i;
Gregory Greenmance792912015-06-02 18:06:16 +0300957
Assaf Krauss3e0fa502015-09-16 11:44:55 +0300958 if (sscanf(data, "%u %hhd %hhd %hhd"
Gregory Greenmance792912015-06-02 18:06:16 +0300959 "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
Assaf Krauss3e0fa502015-09-16 11:44:55 +0300960 "%hhd %hhd %hd"
961 "%hhd %hhd %d"
962 "%hhx %hhd %hhd %hhd",
Gregory Greenmance792912015-06-02 18:06:16 +0300963 &i, &ap.channel_num, &ap.bandwidth,
964 &ap.ctrl_ch_position,
965 mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5,
966 &ap.measure_type, &ap.num_of_bursts,
967 &burst_period,
968 &ap.samples_per_burst, &ap.retries_per_sample,
969 &ap.tsf_delta, &ap.location_req, &ap.asap_mode,
970 &ap.enable_dyn_ack, &ap.rssi) != 20) {
971 ret = -EINVAL;
972 goto out;
973 }
Dan Carpenter5b9d47c2015-08-11 00:45:03 +0300974 if (i >= IWL_MVM_TOF_MAX_APS) {
Gregory Greenmance792912015-06-02 18:06:16 +0300975 IWL_ERR(mvm, "Invalid AP index %d\n", i);
976 ret = -EINVAL;
977 goto out;
978 }
979
980 ap.burst_period = cpu_to_le16(burst_period);
981
982 memcpy(&mvm->tof_data.range_req.ap[i], &ap, size);
983 goto out;
984 }
985
986 data = iwl_dbgfs_is_match("send_range_request=", buf);
987 if (data) {
988 ret = kstrtou32(data, 10, &value);
Assaf Krauss5ac15be2015-09-16 11:47:14 +0300989 if (ret == 0 && value)
Gregory Greenmance792912015-06-02 18:06:16 +0300990 ret = iwl_mvm_tof_range_request_cmd(mvm, vif);
Assaf Krauss5ac15be2015-09-16 11:47:14 +0300991 goto out;
Gregory Greenmance792912015-06-02 18:06:16 +0300992 }
993
Assaf Krauss5ac15be2015-09-16 11:47:14 +0300994 ret = -EINVAL;
Gregory Greenmance792912015-06-02 18:06:16 +0300995out:
996 mutex_unlock(&mvm->mutex);
997 return ret ?: count;
998}
999
1000static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file,
1001 char __user *user_buf,
1002 size_t count, loff_t *ppos)
1003{
1004 struct ieee80211_vif *vif = file->private_data;
1005 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1006 struct iwl_mvm *mvm = mvmvif->mvm;
1007 char buf[512];
1008 int pos = 0;
1009 const size_t bufsz = sizeof(buf);
1010 struct iwl_tof_range_req_cmd *cmd;
1011 int i;
1012
1013 cmd = &mvm->tof_data.range_req;
1014
1015 mutex_lock(&mvm->mutex);
1016
1017 pos += scnprintf(buf + pos, bufsz - pos, "request_id= %d\n",
1018 cmd->request_id);
1019 pos += scnprintf(buf + pos, bufsz - pos, "initiator= %d\n",
1020 cmd->initiator);
1021 pos += scnprintf(buf + pos, bufsz - pos, "one_sided_los_disable = %d\n",
1022 cmd->one_sided_los_disable);
1023 pos += scnprintf(buf + pos, bufsz - pos, "req_timeout= %d\n",
1024 cmd->req_timeout);
1025 pos += scnprintf(buf + pos, bufsz - pos, "report_policy= %d\n",
1026 cmd->report_policy);
1027 pos += scnprintf(buf + pos, bufsz - pos, "macaddr_random= %d\n",
1028 cmd->macaddr_random);
1029 pos += scnprintf(buf + pos, bufsz - pos, "macaddr_template= %pM\n",
1030 cmd->macaddr_template);
1031 pos += scnprintf(buf + pos, bufsz - pos, "macaddr_mask= %pM\n",
1032 cmd->macaddr_mask);
1033 pos += scnprintf(buf + pos, bufsz - pos, "num_of_ap= %d\n",
1034 cmd->num_of_ap);
1035 for (i = 0; i < cmd->num_of_ap; i++) {
1036 struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i];
1037
1038 pos += scnprintf(buf + pos, bufsz - pos,
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001039 "ap %.2d: channel_num=%hhd bw=%hhd"
1040 " control=%hhd bssid=%pM type=%hhd"
1041 " num_of_bursts=%hhd burst_period=%hd ftm=%hhd"
1042 " retries=%hhd tsf_delta=%d"
1043 " tsf_delta_direction=%hhd location_req=0x%hhx "
1044 " asap=%hhd enable=%hhd rssi=%hhd\n",
Gregory Greenmance792912015-06-02 18:06:16 +03001045 i, ap->channel_num, ap->bandwidth,
1046 ap->ctrl_ch_position, ap->bssid,
1047 ap->measure_type, ap->num_of_bursts,
1048 ap->burst_period, ap->samples_per_burst,
1049 ap->retries_per_sample, ap->tsf_delta,
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001050 ap->tsf_delta_direction,
Gregory Greenmance792912015-06-02 18:06:16 +03001051 ap->location_req, ap->asap_mode,
1052 ap->enable_dyn_ack, ap->rssi);
1053 }
1054
1055 mutex_unlock(&mvm->mutex);
1056
1057 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1058}
1059
1060static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif,
1061 char *buf,
1062 size_t count, loff_t *ppos)
1063{
1064 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1065 struct iwl_mvm *mvm = mvmvif->mvm;
Johannes Berge6c21be2015-09-24 22:15:02 +02001066 u32 value;
1067 int ret = 0;
Gregory Greenmance792912015-06-02 18:06:16 +03001068 char *data;
1069
1070 mutex_lock(&mvm->mutex);
1071
1072 data = iwl_dbgfs_is_match("tsf_timer_offset_msec=", buf);
1073 if (data) {
1074 ret = kstrtou32(data, 10, &value);
1075 if (ret == 0)
1076 mvm->tof_data.range_req_ext.tsf_timer_offset_msec =
1077 cpu_to_le16(value);
1078 goto out;
1079 }
1080
1081 data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
1082 if (data) {
1083 ret = kstrtou32(data, 10, &value);
1084 if (ret == 0)
1085 mvm->tof_data.range_req_ext.min_delta_ftm = value;
1086 goto out;
1087 }
1088
1089 data = iwl_dbgfs_is_match("ftm_format_and_bw20M=", buf);
1090 if (data) {
1091 ret = kstrtou32(data, 10, &value);
1092 if (ret == 0)
1093 mvm->tof_data.range_req_ext.ftm_format_and_bw20M =
1094 value;
1095 goto out;
1096 }
1097
1098 data = iwl_dbgfs_is_match("ftm_format_and_bw40M=", buf);
1099 if (data) {
1100 ret = kstrtou32(data, 10, &value);
1101 if (ret == 0)
1102 mvm->tof_data.range_req_ext.ftm_format_and_bw40M =
1103 value;
1104 goto out;
1105 }
1106
1107 data = iwl_dbgfs_is_match("ftm_format_and_bw80M=", buf);
1108 if (data) {
1109 ret = kstrtou32(data, 10, &value);
1110 if (ret == 0)
1111 mvm->tof_data.range_req_ext.ftm_format_and_bw80M =
1112 value;
1113 goto out;
1114 }
1115
1116 data = iwl_dbgfs_is_match("send_range_req_ext=", buf);
1117 if (data) {
1118 ret = kstrtou32(data, 10, &value);
Assaf Krauss5ac15be2015-09-16 11:47:14 +03001119 if (ret == 0 && value)
Gregory Greenmance792912015-06-02 18:06:16 +03001120 ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif);
Assaf Krauss5ac15be2015-09-16 11:47:14 +03001121 goto out;
Gregory Greenmance792912015-06-02 18:06:16 +03001122 }
1123
Assaf Krauss5ac15be2015-09-16 11:47:14 +03001124 ret = -EINVAL;
Gregory Greenmance792912015-06-02 18:06:16 +03001125out:
1126 mutex_unlock(&mvm->mutex);
1127 return ret ?: count;
1128}
1129
1130static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file,
1131 char __user *user_buf,
1132 size_t count, loff_t *ppos)
1133{
1134 struct ieee80211_vif *vif = file->private_data;
1135 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1136 struct iwl_mvm *mvm = mvmvif->mvm;
1137 char buf[256];
1138 int pos = 0;
1139 const size_t bufsz = sizeof(buf);
1140 struct iwl_tof_range_req_ext_cmd *cmd;
1141
1142 cmd = &mvm->tof_data.range_req_ext;
1143
1144 mutex_lock(&mvm->mutex);
1145
1146 pos += scnprintf(buf + pos, bufsz - pos,
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001147 "tsf_timer_offset_msec = %hd\n",
Gregory Greenmance792912015-06-02 18:06:16 +03001148 cmd->tsf_timer_offset_msec);
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001149 pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n",
Gregory Greenmance792912015-06-02 18:06:16 +03001150 cmd->min_delta_ftm);
1151 pos += scnprintf(buf + pos, bufsz - pos,
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001152 "ftm_format_and_bw20M = %hhd\n",
Gregory Greenmance792912015-06-02 18:06:16 +03001153 cmd->ftm_format_and_bw20M);
1154 pos += scnprintf(buf + pos, bufsz - pos,
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001155 "ftm_format_and_bw40M = %hhd\n",
Gregory Greenmance792912015-06-02 18:06:16 +03001156 cmd->ftm_format_and_bw40M);
1157 pos += scnprintf(buf + pos, bufsz - pos,
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001158 "ftm_format_and_bw80M = %hhd\n",
Gregory Greenmance792912015-06-02 18:06:16 +03001159 cmd->ftm_format_and_bw80M);
1160
1161 mutex_unlock(&mvm->mutex);
1162 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1163}
1164
1165static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif,
1166 char *buf,
1167 size_t count, loff_t *ppos)
1168{
1169 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1170 struct iwl_mvm *mvm = mvmvif->mvm;
Johannes Berge6c21be2015-09-24 22:15:02 +02001171 u32 value;
1172 int abort_id, ret = 0;
Gregory Greenmance792912015-06-02 18:06:16 +03001173 char *data;
1174
1175 mutex_lock(&mvm->mutex);
1176
1177 data = iwl_dbgfs_is_match("abort_id=", buf);
1178 if (data) {
1179 ret = kstrtou32(data, 10, &value);
1180 if (ret == 0)
1181 mvm->tof_data.last_abort_id = value;
1182 goto out;
1183 }
1184
1185 data = iwl_dbgfs_is_match("send_range_abort=", buf);
1186 if (data) {
1187 ret = kstrtou32(data, 10, &value);
1188 if (ret == 0 && value) {
1189 abort_id = mvm->tof_data.last_abort_id;
1190 ret = iwl_mvm_tof_range_abort_cmd(mvm, abort_id);
1191 goto out;
1192 }
1193 }
1194
1195out:
1196 mutex_unlock(&mvm->mutex);
1197 return ret ?: count;
1198}
1199
1200static ssize_t iwl_dbgfs_tof_range_abort_read(struct file *file,
1201 char __user *user_buf,
1202 size_t count, loff_t *ppos)
1203{
1204 struct ieee80211_vif *vif = file->private_data;
1205 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1206 struct iwl_mvm *mvm = mvmvif->mvm;
1207 char buf[32];
1208 int pos = 0;
1209 const size_t bufsz = sizeof(buf);
1210 int last_abort_id;
1211
1212 mutex_lock(&mvm->mutex);
1213 last_abort_id = mvm->tof_data.last_abort_id;
1214 mutex_unlock(&mvm->mutex);
1215
1216 pos += scnprintf(buf + pos, bufsz - pos, "last_abort_id = %d\n",
1217 last_abort_id);
1218 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1219}
1220
1221static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file,
1222 char __user *user_buf,
1223 size_t count, loff_t *ppos)
1224{
1225 struct ieee80211_vif *vif = file->private_data;
1226 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1227 struct iwl_mvm *mvm = mvmvif->mvm;
1228 char *buf;
1229 int pos = 0;
1230 const size_t bufsz = sizeof(struct iwl_tof_range_rsp_ntfy) + 256;
1231 struct iwl_tof_range_rsp_ntfy *cmd;
1232 int i, ret;
1233
1234 buf = kzalloc(bufsz, GFP_KERNEL);
1235 if (!buf)
1236 return -ENOMEM;
1237
1238 mutex_lock(&mvm->mutex);
1239 cmd = &mvm->tof_data.range_resp;
1240
1241 pos += scnprintf(buf + pos, bufsz - pos, "request_id = %d\n",
1242 cmd->request_id);
1243 pos += scnprintf(buf + pos, bufsz - pos, "status = %d\n",
1244 cmd->request_status);
1245 pos += scnprintf(buf + pos, bufsz - pos, "last_in_batch = %d\n",
1246 cmd->last_in_batch);
1247 pos += scnprintf(buf + pos, bufsz - pos, "num_of_aps = %d\n",
1248 cmd->num_of_aps);
1249 for (i = 0; i < cmd->num_of_aps; i++) {
1250 struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i];
1251
1252 pos += scnprintf(buf + pos, bufsz - pos,
Assaf Krauss3e0fa502015-09-16 11:44:55 +03001253 "ap %.2d: bssid=%pM status=%hhd bw=%hhd"
1254 " rtt=%d rtt_var=%d rtt_spread=%d"
1255 " rssi=%hhd rssi_spread=%hhd"
1256 " range=%d range_var=%d"
1257 " time_stamp=%d\n",
Gregory Greenmance792912015-06-02 18:06:16 +03001258 i, ap->bssid, ap->measure_status,
1259 ap->measure_bw,
1260 ap->rtt, ap->rtt_variance, ap->rtt_spread,
1261 ap->rssi, ap->rssi_spread, ap->range,
1262 ap->range_variance, ap->timestamp);
1263 }
1264 mutex_unlock(&mvm->mutex);
1265
1266 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1267 kfree(buf);
1268 return ret;
1269}
1270
Johannes Berga21d7bc2013-11-12 17:30:52 +01001271static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
1272 size_t count, loff_t *ppos)
1273{
1274 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1275 struct iwl_mvm *mvm = mvmvif->mvm;
1276 u8 value;
1277 int ret;
1278
1279 ret = kstrtou8(buf, 0, &value);
1280 if (ret)
1281 return ret;
1282 if (value > 1)
1283 return -EINVAL;
1284
1285 mutex_lock(&mvm->mutex);
Sara Sharon9b137862017-12-27 12:16:33 +02001286 iwl_mvm_update_low_latency(mvm, vif, value, LOW_LATENCY_DEBUGFS);
Johannes Berga21d7bc2013-11-12 17:30:52 +01001287 mutex_unlock(&mvm->mutex);
1288
1289 return count;
1290}
1291
1292static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
1293 char __user *user_buf,
1294 size_t count, loff_t *ppos)
1295{
1296 struct ieee80211_vif *vif = file->private_data;
1297 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
Johannes Bergb525d082016-01-06 10:01:41 +01001298 char buf[30] = {};
1299 int len;
Johannes Berga21d7bc2013-11-12 17:30:52 +01001300
Johannes Berg40e86a32017-04-19 09:58:50 +02001301 len = scnprintf(buf, sizeof(buf) - 1,
1302 "traffic=%d\ndbgfs=%d\nvcmd=%d\n",
Sara Sharon9b137862017-12-27 12:16:33 +02001303 !!(mvmvif->low_latency & LOW_LATENCY_TRAFFIC),
1304 !!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS),
1305 !!(mvmvif->low_latency & LOW_LATENCY_VCMD));
Johannes Bergb525d082016-01-06 10:01:41 +01001306 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Johannes Berga21d7bc2013-11-12 17:30:52 +01001307}
1308
Johannes Berge39c1b52015-01-09 14:15:32 +01001309static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file,
1310 char __user *user_buf,
1311 size_t count, loff_t *ppos)
1312{
1313 struct ieee80211_vif *vif = file->private_data;
1314 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1315 char buf[20];
1316 int len;
1317
1318 len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid);
1319 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1320}
1321
1322static ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif,
1323 char *buf, size_t count,
1324 loff_t *ppos)
1325{
1326 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1327 struct iwl_mvm *mvm = mvmvif->mvm;
1328 bool ret;
1329
1330 mutex_lock(&mvm->mutex);
1331 ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid);
1332 mutex_unlock(&mvm->mutex);
1333
1334 return ret ? count : -EINVAL;
1335}
1336
Emmanuel Grumbachddf89ab2015-02-08 10:56:43 +02001337static ssize_t iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif *vif, char *buf,
1338 size_t count, loff_t *ppos)
1339{
1340 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1341 struct iwl_mvm *mvm = mvmvif->mvm;
1342 struct ieee80211_chanctx_conf *chanctx_conf;
1343 struct iwl_mvm_phy_ctxt *phy_ctxt;
1344 u16 value;
1345 int ret;
1346
1347 ret = kstrtou16(buf, 0, &value);
1348 if (ret)
1349 return ret;
1350
1351 mutex_lock(&mvm->mutex);
1352 rcu_read_lock();
1353
1354 chanctx_conf = rcu_dereference(vif->chanctx_conf);
1355 /* make sure the channel context is assigned */
1356 if (!chanctx_conf) {
1357 rcu_read_unlock();
1358 mutex_unlock(&mvm->mutex);
1359 return -EINVAL;
1360 }
1361
1362 phy_ctxt = &mvm->phy_ctxts[*(u16 *)chanctx_conf->drv_priv];
1363 rcu_read_unlock();
1364
1365 mvm->dbgfs_rx_phyinfo = value;
1366
1367 ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chanctx_conf->min_def,
1368 chanctx_conf->rx_chains_static,
1369 chanctx_conf->rx_chains_dynamic);
1370 mutex_unlock(&mvm->mutex);
1371
1372 return ret ?: count;
1373}
1374
1375static ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file,
1376 char __user *user_buf,
1377 size_t count, loff_t *ppos)
1378{
1379 struct ieee80211_vif *vif = file->private_data;
1380 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1381 char buf[8];
Johannes Berg40e86a32017-04-19 09:58:50 +02001382 int len;
Emmanuel Grumbachddf89ab2015-02-08 10:56:43 +02001383
Johannes Berg40e86a32017-04-19 09:58:50 +02001384 len = scnprintf(buf, sizeof(buf), "0x%04x\n",
1385 mvmvif->mvm->dbgfs_rx_phyinfo);
Emmanuel Grumbachddf89ab2015-02-08 10:56:43 +02001386
Johannes Berg40e86a32017-04-19 09:58:50 +02001387 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
Emmanuel Grumbachddf89ab2015-02-08 10:56:43 +02001388}
1389
Johannes Berga80c1cf2016-01-13 15:01:00 +01001390static void iwl_dbgfs_quota_check(void *data, u8 *mac,
1391 struct ieee80211_vif *vif)
1392{
1393 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1394 int *ret = data;
1395
1396 if (mvmvif->dbgfs_quota_min)
1397 *ret = -EINVAL;
1398}
1399
1400static ssize_t iwl_dbgfs_quota_min_write(struct ieee80211_vif *vif, char *buf,
1401 size_t count, loff_t *ppos)
1402{
1403 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1404 struct iwl_mvm *mvm = mvmvif->mvm;
1405 u16 value;
1406 int ret;
1407
1408 ret = kstrtou16(buf, 0, &value);
1409 if (ret)
1410 return ret;
1411
1412 if (value > 95)
1413 return -EINVAL;
1414
1415 mutex_lock(&mvm->mutex);
1416
1417 mvmvif->dbgfs_quota_min = 0;
1418 ieee80211_iterate_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1419 iwl_dbgfs_quota_check, &ret);
1420 if (ret == 0) {
1421 mvmvif->dbgfs_quota_min = value;
1422 iwl_mvm_update_quotas(mvm, false, NULL);
1423 }
1424 mutex_unlock(&mvm->mutex);
1425
1426 return ret ?: count;
1427}
1428
1429static ssize_t iwl_dbgfs_quota_min_read(struct file *file,
1430 char __user *user_buf,
1431 size_t count, loff_t *ppos)
1432{
1433 struct ieee80211_vif *vif = file->private_data;
1434 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1435 char buf[10];
1436 int len;
1437
Johannes Berg40e86a32017-04-19 09:58:50 +02001438 len = scnprintf(buf, sizeof(buf), "%d\n", mvmvif->dbgfs_quota_min);
Johannes Berga80c1cf2016-01-13 15:01:00 +01001439
1440 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1441}
1442
Aviya Erenfelddedfc0f2016-03-13 15:58:59 +02001443static const char * const chanwidths[] = {
1444 [NL80211_CHAN_WIDTH_20_NOHT] = "noht",
1445 [NL80211_CHAN_WIDTH_20] = "ht20",
1446 [NL80211_CHAN_WIDTH_40] = "ht40",
1447 [NL80211_CHAN_WIDTH_80] = "vht80",
1448 [NL80211_CHAN_WIDTH_80P80] = "vht80p80",
1449 [NL80211_CHAN_WIDTH_160] = "vht160",
1450};
1451
Alexander Bondare45a9412013-12-04 10:13:24 +02001452#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1453 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1454#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1455 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
Johannes Berg820a1a52013-11-12 16:58:41 +01001456#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
1457 if (!debugfs_create_file(#name, mode, parent, vif, \
1458 &iwl_dbgfs_##name##_ops)) \
1459 goto err; \
1460 } while (0)
1461
1462MVM_DEBUGFS_READ_FILE_OPS(mac_params);
Matti Gottlieb25870cb2015-05-04 09:34:37 +03001463MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
Alexander Bondare45a9412013-12-04 10:13:24 +02001464MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
1465MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
Johannes Berga21d7bc2013-11-12 17:30:52 +01001466MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
Johannes Berge39c1b52015-01-09 14:15:32 +01001467MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
Emmanuel Grumbachddf89ab2015-02-08 10:56:43 +02001468MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
Gregory Greenmance792912015-06-02 18:06:16 +03001469MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable, 32);
1470MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request, 512);
1471MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32);
1472MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32);
1473MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
1474MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
Johannes Berga80c1cf2016-01-13 15:01:00 +01001475MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
Roee Zamirb3bee582016-08-02 13:55:13 +03001476MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
1477
Johannes Berg820a1a52013-11-12 16:58:41 +01001478
1479void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1480{
1481 struct dentry *dbgfs_dir = vif->debugfs_dir;
1482 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1483 char buf[100];
1484
1485 /*
1486 * Check if debugfs directory already exist before creating it.
1487 * This may happen when, for example, resetting hw or suspend-resume
1488 */
1489 if (!dbgfs_dir || mvmvif->dbgfs_dir)
1490 return;
1491
1492 mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
Johannes Berg820a1a52013-11-12 16:58:41 +01001493
1494 if (!mvmvif->dbgfs_dir) {
Al Viro27a22092016-08-07 12:21:25 -04001495 IWL_ERR(mvm, "Failed to create debugfs directory under %pd\n",
1496 dbgfs_dir);
Johannes Berg820a1a52013-11-12 16:58:41 +01001497 return;
1498 }
1499
Emmanuel Grumbachad2549d2014-03-30 09:50:54 +03001500 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
Alexander Bondare45a9412013-12-04 10:13:24 +02001501 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
Luca Coelho4b87e5a2016-09-12 16:03:30 +03001502 (vif->type == NL80211_IFTYPE_STATION && vif->p2p)))
Joe Perches2ef00c52018-03-23 15:54:37 -07001503 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, 0600);
Alexander Bondare45a9412013-12-04 10:13:24 +02001504
Joe Perches2ef00c52018-03-23 15:54:37 -07001505 MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, 0400);
1506 MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, 0400);
1507 MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, 0600);
1508 MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir, 0600);
1509 MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, 0600);
1510 MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, 0600);
1511 MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff, mvmvif->dbgfs_dir, 0400);
Johannes Berg820a1a52013-11-12 16:58:41 +01001512
Alexander Bondare45a9412013-12-04 10:13:24 +02001513 if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
1514 mvmvif == mvm->bf_allowed_vif)
Joe Perches2ef00c52018-03-23 15:54:37 -07001515 MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, 0600);
Alexander Bondare45a9412013-12-04 10:13:24 +02001516
Gregory Greenmance792912015-06-02 18:06:16 +03001517 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT) &&
1518 !vif->p2p && (vif->type != NL80211_IFTYPE_P2P_DEVICE)) {
1519 if (IWL_MVM_TOF_IS_RESPONDER && vif->type == NL80211_IFTYPE_AP)
1520 MVM_DEBUGFS_ADD_FILE_VIF(tof_responder_params,
Joe Perches2ef00c52018-03-23 15:54:37 -07001521 mvmvif->dbgfs_dir, 0600);
Gregory Greenmance792912015-06-02 18:06:16 +03001522
1523 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_request, mvmvif->dbgfs_dir,
Joe Perches2ef00c52018-03-23 15:54:37 -07001524 0600);
Gregory Greenmance792912015-06-02 18:06:16 +03001525 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_req_ext, mvmvif->dbgfs_dir,
Joe Perches2ef00c52018-03-23 15:54:37 -07001526 0600);
Gregory Greenmance792912015-06-02 18:06:16 +03001527 MVM_DEBUGFS_ADD_FILE_VIF(tof_enable, mvmvif->dbgfs_dir,
Joe Perches2ef00c52018-03-23 15:54:37 -07001528 0600);
Gregory Greenmance792912015-06-02 18:06:16 +03001529 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_abort, mvmvif->dbgfs_dir,
Joe Perches2ef00c52018-03-23 15:54:37 -07001530 0600);
Gregory Greenmance792912015-06-02 18:06:16 +03001531 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_response, mvmvif->dbgfs_dir,
Joe Perches2ef00c52018-03-23 15:54:37 -07001532 0400);
Gregory Greenmance792912015-06-02 18:06:16 +03001533 }
1534
Johannes Berg820a1a52013-11-12 16:58:41 +01001535 /*
1536 * Create symlink for convenience pointing to interface specific
1537 * debugfs entries for the driver. For example, under
1538 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1539 * find
1540 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1541 */
Al Viro27a22092016-08-07 12:21:25 -04001542 snprintf(buf, 100, "../../../%pd3/%pd",
1543 dbgfs_dir,
1544 mvmvif->dbgfs_dir);
Johannes Berg820a1a52013-11-12 16:58:41 +01001545
1546 mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
1547 mvm->debugfs_dir, buf);
1548 if (!mvmvif->dbgfs_slink)
Al Viro27a22092016-08-07 12:21:25 -04001549 IWL_ERR(mvm, "Can't create debugfs symbolic link under %pd\n",
1550 dbgfs_dir);
Johannes Berg820a1a52013-11-12 16:58:41 +01001551 return;
1552err:
1553 IWL_ERR(mvm, "Can't create debugfs entity\n");
1554}
1555
1556void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1557{
1558 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1559
1560 debugfs_remove(mvmvif->dbgfs_slink);
1561 mvmvif->dbgfs_slink = NULL;
1562
1563 debugfs_remove_recursive(mvmvif->dbgfs_dir);
1564 mvmvif->dbgfs_dir = NULL;
1565}