1 /******************************************************************************
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.
8 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
25 * The full GNU General Public License is included in this distribution
26 * in the file called COPYING.
28 * Contact Information:
29 * Intel Linux Wireless <ilw@linux.intel.com>
30 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
34 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
35 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
36 * All rights reserved.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
42 * * Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * * Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in
46 * the documentation and/or other materials provided with the
48 * * Neither the name Intel Corporation nor the names of its
49 * contributors may be used to endorse or promote products derived
50 * from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
53 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
54 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
55 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
56 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
57 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
58 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
62 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 *****************************************************************************/
66 #include "fw-api-tof.h"
69 static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
70 struct ieee80211_vif *vif,
71 enum iwl_dbgfs_pm_mask param, int val)
73 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
74 struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
76 dbgfs_pm->mask |= param;
79 case MVM_DEBUGFS_PM_KEEP_ALIVE: {
80 int dtimper = vif->bss_conf.dtim_period ?: 1;
81 int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
83 IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
84 if (val * MSEC_PER_SEC < 3 * dtimper_msec)
86 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
87 val * MSEC_PER_SEC, 3 * dtimper_msec);
88 dbgfs_pm->keep_alive_seconds = val;
91 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
92 IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
93 val ? "enabled" : "disabled");
94 dbgfs_pm->skip_over_dtim = val;
96 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
97 IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
98 dbgfs_pm->skip_dtim_periods = val;
100 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
101 IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
102 dbgfs_pm->rx_data_timeout = val;
104 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
105 IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
106 dbgfs_pm->tx_data_timeout = val;
108 case MVM_DEBUGFS_PM_LPRX_ENA:
109 IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
110 dbgfs_pm->lprx_ena = val;
112 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
113 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
114 dbgfs_pm->lprx_rssi_threshold = val;
116 case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
117 IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
118 dbgfs_pm->snooze_ena = val;
120 case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING:
121 IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val);
122 dbgfs_pm->uapsd_misbehaving = val;
124 case MVM_DEBUGFS_PM_USE_PS_POLL:
125 IWL_DEBUG_POWER(mvm, "use_ps_poll=%d\n", val);
126 dbgfs_pm->use_ps_poll = val;
131 static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
132 size_t count, loff_t *ppos)
134 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
135 struct iwl_mvm *mvm = mvmvif->mvm;
136 enum iwl_dbgfs_pm_mask param;
139 if (!strncmp("keep_alive=", buf, 11)) {
140 if (sscanf(buf + 11, "%d", &val) != 1)
142 param = MVM_DEBUGFS_PM_KEEP_ALIVE;
143 } else if (!strncmp("skip_over_dtim=", buf, 15)) {
144 if (sscanf(buf + 15, "%d", &val) != 1)
146 param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
147 } else if (!strncmp("skip_dtim_periods=", buf, 18)) {
148 if (sscanf(buf + 18, "%d", &val) != 1)
150 param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
151 } else if (!strncmp("rx_data_timeout=", buf, 16)) {
152 if (sscanf(buf + 16, "%d", &val) != 1)
154 param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
155 } else if (!strncmp("tx_data_timeout=", buf, 16)) {
156 if (sscanf(buf + 16, "%d", &val) != 1)
158 param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
159 } else if (!strncmp("lprx=", buf, 5)) {
160 if (sscanf(buf + 5, "%d", &val) != 1)
162 param = MVM_DEBUGFS_PM_LPRX_ENA;
163 } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
164 if (sscanf(buf + 20, "%d", &val) != 1)
166 if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
167 POWER_LPRX_RSSI_THRESHOLD_MIN)
169 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
170 } else if (!strncmp("snooze_enable=", buf, 14)) {
171 if (sscanf(buf + 14, "%d", &val) != 1)
173 param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
174 } else if (!strncmp("uapsd_misbehaving=", buf, 18)) {
175 if (sscanf(buf + 18, "%d", &val) != 1)
177 param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING;
178 } else if (!strncmp("use_ps_poll=", buf, 12)) {
179 if (sscanf(buf + 12, "%d", &val) != 1)
181 param = MVM_DEBUGFS_PM_USE_PS_POLL;
186 mutex_lock(&mvm->mutex);
187 iwl_dbgfs_update_pm(mvm, vif, param, val);
188 ret = iwl_mvm_power_update_mac(mvm);
189 mutex_unlock(&mvm->mutex);
194 static ssize_t iwl_dbgfs_tx_pwr_lmt_read(struct file *file,
195 char __user *user_buf,
196 size_t count, loff_t *ppos)
198 struct ieee80211_vif *vif = file->private_data;
200 int bufsz = sizeof(buf);
203 pos = scnprintf(buf, bufsz, "bss limit = %d\n",
204 vif->bss_conf.txpower);
206 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
209 static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
210 char __user *user_buf,
211 size_t count, loff_t *ppos)
213 struct ieee80211_vif *vif = file->private_data;
214 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
215 struct iwl_mvm *mvm = mvmvif->mvm;
217 int bufsz = sizeof(buf);
220 pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
222 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
225 static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
226 char __user *user_buf,
227 size_t count, loff_t *ppos)
229 struct ieee80211_vif *vif = file->private_data;
230 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
231 struct iwl_mvm *mvm = mvmvif->mvm;
233 struct ieee80211_chanctx_conf *chanctx_conf;
235 int bufsz = sizeof(buf);
239 mutex_lock(&mvm->mutex);
241 ap_sta_id = mvmvif->ap_sta_id;
243 switch (ieee80211_vif_type_p2p(vif)) {
244 case NL80211_IFTYPE_ADHOC:
245 pos += scnprintf(buf+pos, bufsz-pos, "type: ibss\n");
247 case NL80211_IFTYPE_STATION:
248 pos += scnprintf(buf+pos, bufsz-pos, "type: bss\n");
250 case NL80211_IFTYPE_AP:
251 pos += scnprintf(buf+pos, bufsz-pos, "type: ap\n");
253 case NL80211_IFTYPE_P2P_CLIENT:
254 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p client\n");
256 case NL80211_IFTYPE_P2P_GO:
257 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p go\n");
259 case NL80211_IFTYPE_P2P_DEVICE:
260 pos += scnprintf(buf+pos, bufsz-pos, "type: p2p dev\n");
266 pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
267 mvmvif->id, mvmvif->color);
268 pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
269 vif->bss_conf.bssid);
270 pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
271 for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
272 pos += scnprintf(buf+pos, bufsz-pos,
273 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
274 i, mvmvif->queue_params[i].txop,
275 mvmvif->queue_params[i].cw_min,
276 mvmvif->queue_params[i].cw_max,
277 mvmvif->queue_params[i].aifs,
278 mvmvif->queue_params[i].uapsd);
280 if (vif->type == NL80211_IFTYPE_STATION &&
281 ap_sta_id != IWL_MVM_STATION_COUNT) {
282 struct ieee80211_sta *sta;
284 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
285 lockdep_is_held(&mvm->mutex));
286 if (!IS_ERR_OR_NULL(sta)) {
287 struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
289 pos += scnprintf(buf+pos, bufsz-pos,
290 "ap_sta_id %d - reduced Tx power %d\n",
292 mvm_sta->bt_reduced_txpower);
297 chanctx_conf = rcu_dereference(vif->chanctx_conf);
299 pos += scnprintf(buf+pos, bufsz-pos,
300 "idle rx chains %d, active rx chains: %d\n",
301 chanctx_conf->rx_chains_static,
302 chanctx_conf->rx_chains_dynamic);
305 mutex_unlock(&mvm->mutex);
307 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
310 static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
311 enum iwl_dbgfs_bf_mask param, int value)
313 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
314 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
316 dbgfs_bf->mask |= param;
319 case MVM_DEBUGFS_BF_ENERGY_DELTA:
320 dbgfs_bf->bf_energy_delta = value;
322 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
323 dbgfs_bf->bf_roaming_energy_delta = value;
325 case MVM_DEBUGFS_BF_ROAMING_STATE:
326 dbgfs_bf->bf_roaming_state = value;
328 case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
329 dbgfs_bf->bf_temp_threshold = value;
331 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
332 dbgfs_bf->bf_temp_fast_filter = value;
334 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
335 dbgfs_bf->bf_temp_slow_filter = value;
337 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
338 dbgfs_bf->bf_enable_beacon_filter = value;
340 case MVM_DEBUGFS_BF_DEBUG_FLAG:
341 dbgfs_bf->bf_debug_flag = value;
343 case MVM_DEBUGFS_BF_ESCAPE_TIMER:
344 dbgfs_bf->bf_escape_timer = value;
346 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
347 dbgfs_bf->ba_enable_beacon_abort = value;
349 case MVM_DEBUGFS_BA_ESCAPE_TIMER:
350 dbgfs_bf->ba_escape_timer = value;
355 static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
356 size_t count, loff_t *ppos)
358 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
359 struct iwl_mvm *mvm = mvmvif->mvm;
360 enum iwl_dbgfs_bf_mask param;
363 if (!strncmp("bf_energy_delta=", buf, 16)) {
364 if (sscanf(buf+16, "%d", &value) != 1)
366 if (value < IWL_BF_ENERGY_DELTA_MIN ||
367 value > IWL_BF_ENERGY_DELTA_MAX)
369 param = MVM_DEBUGFS_BF_ENERGY_DELTA;
370 } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
371 if (sscanf(buf+24, "%d", &value) != 1)
373 if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
374 value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
376 param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
377 } else if (!strncmp("bf_roaming_state=", buf, 17)) {
378 if (sscanf(buf+17, "%d", &value) != 1)
380 if (value < IWL_BF_ROAMING_STATE_MIN ||
381 value > IWL_BF_ROAMING_STATE_MAX)
383 param = MVM_DEBUGFS_BF_ROAMING_STATE;
384 } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
385 if (sscanf(buf+18, "%d", &value) != 1)
387 if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
388 value > IWL_BF_TEMP_THRESHOLD_MAX)
390 param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
391 } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
392 if (sscanf(buf+20, "%d", &value) != 1)
394 if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
395 value > IWL_BF_TEMP_FAST_FILTER_MAX)
397 param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
398 } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
399 if (sscanf(buf+20, "%d", &value) != 1)
401 if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
402 value > IWL_BF_TEMP_SLOW_FILTER_MAX)
404 param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
405 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
406 if (sscanf(buf+24, "%d", &value) != 1)
408 if (value < 0 || value > 1)
410 param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
411 } else if (!strncmp("bf_debug_flag=", buf, 14)) {
412 if (sscanf(buf+14, "%d", &value) != 1)
414 if (value < 0 || value > 1)
416 param = MVM_DEBUGFS_BF_DEBUG_FLAG;
417 } else if (!strncmp("bf_escape_timer=", buf, 16)) {
418 if (sscanf(buf+16, "%d", &value) != 1)
420 if (value < IWL_BF_ESCAPE_TIMER_MIN ||
421 value > IWL_BF_ESCAPE_TIMER_MAX)
423 param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
424 } else if (!strncmp("ba_escape_timer=", buf, 16)) {
425 if (sscanf(buf+16, "%d", &value) != 1)
427 if (value < IWL_BA_ESCAPE_TIMER_MIN ||
428 value > IWL_BA_ESCAPE_TIMER_MAX)
430 param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
431 } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
432 if (sscanf(buf+23, "%d", &value) != 1)
434 if (value < 0 || value > 1)
436 param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
441 mutex_lock(&mvm->mutex);
442 iwl_dbgfs_update_bf(vif, param, value);
443 if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
444 ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
446 ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
447 mutex_unlock(&mvm->mutex);
452 static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
453 char __user *user_buf,
454 size_t count, loff_t *ppos)
456 struct ieee80211_vif *vif = file->private_data;
457 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
460 const size_t bufsz = sizeof(buf);
461 struct iwl_beacon_filter_cmd cmd = {
462 IWL_BF_CMD_CONFIG_DEFAULTS,
463 .bf_enable_beacon_filter =
464 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
465 .ba_enable_beacon_abort =
466 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
469 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
470 if (mvmvif->bf_data.bf_enabled)
471 cmd.bf_enable_beacon_filter = cpu_to_le32(1);
473 cmd.bf_enable_beacon_filter = 0;
475 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
476 le32_to_cpu(cmd.bf_energy_delta));
477 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
478 le32_to_cpu(cmd.bf_roaming_energy_delta));
479 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
480 le32_to_cpu(cmd.bf_roaming_state));
481 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
482 le32_to_cpu(cmd.bf_temp_threshold));
483 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
484 le32_to_cpu(cmd.bf_temp_fast_filter));
485 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
486 le32_to_cpu(cmd.bf_temp_slow_filter));
487 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
488 le32_to_cpu(cmd.bf_enable_beacon_filter));
489 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
490 le32_to_cpu(cmd.bf_debug_flag));
491 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
492 le32_to_cpu(cmd.bf_escape_timer));
493 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
494 le32_to_cpu(cmd.ba_escape_timer));
495 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
496 le32_to_cpu(cmd.ba_enable_beacon_abort));
498 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
501 static inline char *iwl_dbgfs_is_match(char *name, char *buf)
503 int len = strlen(name);
505 return !strncmp(name, buf, len) ? buf + len : NULL;
508 static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif,
510 size_t count, loff_t *ppos)
512 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
513 struct iwl_mvm *mvm = mvmvif->mvm;
518 mutex_lock(&mvm->mutex);
520 data = iwl_dbgfs_is_match("tof_disabled=", buf);
522 ret = kstrtou32(data, 10, &value);
524 mvm->tof_data.tof_cfg.tof_disabled = value;
528 data = iwl_dbgfs_is_match("one_sided_disabled=", buf);
530 ret = kstrtou32(data, 10, &value);
532 mvm->tof_data.tof_cfg.one_sided_disabled = value;
536 data = iwl_dbgfs_is_match("is_debug_mode=", buf);
538 ret = kstrtou32(data, 10, &value);
540 mvm->tof_data.tof_cfg.is_debug_mode = value;
544 data = iwl_dbgfs_is_match("is_buf=", buf);
546 ret = kstrtou32(data, 10, &value);
548 mvm->tof_data.tof_cfg.is_buf_required = value;
552 data = iwl_dbgfs_is_match("send_tof_cfg=", buf);
554 ret = kstrtou32(data, 10, &value);
555 if (ret == 0 && value) {
556 ret = iwl_mvm_tof_config_cmd(mvm);
562 mutex_unlock(&mvm->mutex);
567 static ssize_t iwl_dbgfs_tof_enable_read(struct file *file,
568 char __user *user_buf,
569 size_t count, loff_t *ppos)
571 struct ieee80211_vif *vif = file->private_data;
572 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
573 struct iwl_mvm *mvm = mvmvif->mvm;
576 const size_t bufsz = sizeof(buf);
577 struct iwl_tof_config_cmd *cmd;
579 cmd = &mvm->tof_data.tof_cfg;
581 mutex_lock(&mvm->mutex);
583 pos += scnprintf(buf + pos, bufsz - pos, "tof_disabled = %d\n",
585 pos += scnprintf(buf + pos, bufsz - pos, "one_sided_disabled = %d\n",
586 cmd->one_sided_disabled);
587 pos += scnprintf(buf + pos, bufsz - pos, "is_debug_mode = %d\n",
589 pos += scnprintf(buf + pos, bufsz - pos, "is_buf_required = %d\n",
590 cmd->is_buf_required);
592 mutex_unlock(&mvm->mutex);
594 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
597 static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif,
599 size_t count, loff_t *ppos)
601 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
602 struct iwl_mvm *mvm = mvmvif->mvm;
607 mutex_lock(&mvm->mutex);
609 data = iwl_dbgfs_is_match("burst_period=", buf);
611 ret = kstrtou32(data, 10, &value);
613 mvm->tof_data.responder_cfg.burst_period =
618 data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
620 ret = kstrtou32(data, 10, &value);
622 mvm->tof_data.responder_cfg.min_delta_ftm = value;
626 data = iwl_dbgfs_is_match("burst_duration=", buf);
628 ret = kstrtou32(data, 10, &value);
630 mvm->tof_data.responder_cfg.burst_duration = value;
634 data = iwl_dbgfs_is_match("num_of_burst_exp=", buf);
636 ret = kstrtou32(data, 10, &value);
638 mvm->tof_data.responder_cfg.num_of_burst_exp = value;
642 data = iwl_dbgfs_is_match("abort_responder=", buf);
644 ret = kstrtou32(data, 10, &value);
646 mvm->tof_data.responder_cfg.abort_responder = value;
650 data = iwl_dbgfs_is_match("get_ch_est=", buf);
652 ret = kstrtou32(data, 10, &value);
654 mvm->tof_data.responder_cfg.get_ch_est = value;
658 data = iwl_dbgfs_is_match("recv_sta_req_params=", buf);
660 ret = kstrtou32(data, 10, &value);
662 mvm->tof_data.responder_cfg.recv_sta_req_params = value;
666 data = iwl_dbgfs_is_match("channel_num=", buf);
668 ret = kstrtou32(data, 10, &value);
670 mvm->tof_data.responder_cfg.channel_num = value;
674 data = iwl_dbgfs_is_match("bandwidth=", buf);
676 ret = kstrtou32(data, 10, &value);
678 mvm->tof_data.responder_cfg.bandwidth = value;
682 data = iwl_dbgfs_is_match("rate=", buf);
684 ret = kstrtou32(data, 10, &value);
686 mvm->tof_data.responder_cfg.rate = value;
690 data = iwl_dbgfs_is_match("bssid=", buf);
692 u8 *mac = mvm->tof_data.responder_cfg.bssid;
694 if (!mac_pton(data, mac)) {
700 data = iwl_dbgfs_is_match("tsf_timer_offset_msecs=", buf);
702 ret = kstrtou32(data, 10, &value);
704 mvm->tof_data.responder_cfg.tsf_timer_offset_msecs =
709 data = iwl_dbgfs_is_match("toa_offset=", buf);
711 ret = kstrtou32(data, 10, &value);
713 mvm->tof_data.responder_cfg.toa_offset =
718 data = iwl_dbgfs_is_match("center_freq=", buf);
720 struct iwl_tof_responder_config_cmd *cmd =
721 &mvm->tof_data.responder_cfg;
723 ret = kstrtou32(data, 10, &value);
724 if (ret == 0 && value) {
725 enum ieee80211_band band = (cmd->channel_num <= 14) ?
726 IEEE80211_BAND_2GHZ :
728 struct ieee80211_channel chn = {
730 .center_freq = ieee80211_channel_to_frequency(
731 cmd->channel_num, band),
733 struct cfg80211_chan_def chandef = {
736 ieee80211_channel_to_frequency(value,
740 cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef);
745 data = iwl_dbgfs_is_match("ftm_per_burst=", buf);
747 ret = kstrtou32(data, 10, &value);
749 mvm->tof_data.responder_cfg.ftm_per_burst = value;
753 data = iwl_dbgfs_is_match("ftm_resp_ts_avail=", buf);
755 ret = kstrtou32(data, 10, &value);
757 mvm->tof_data.responder_cfg.ftm_resp_ts_avail = value;
761 data = iwl_dbgfs_is_match("asap_mode=", buf);
763 ret = kstrtou32(data, 10, &value);
765 mvm->tof_data.responder_cfg.asap_mode = value;
769 data = iwl_dbgfs_is_match("send_responder_cfg=", buf);
771 ret = kstrtou32(data, 10, &value);
772 if (ret == 0 && value) {
773 ret = iwl_mvm_tof_responder_cmd(mvm, vif);
779 mutex_unlock(&mvm->mutex);
784 static ssize_t iwl_dbgfs_tof_responder_params_read(struct file *file,
785 char __user *user_buf,
786 size_t count, loff_t *ppos)
788 struct ieee80211_vif *vif = file->private_data;
789 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
790 struct iwl_mvm *mvm = mvmvif->mvm;
793 const size_t bufsz = sizeof(buf);
794 struct iwl_tof_responder_config_cmd *cmd;
796 cmd = &mvm->tof_data.responder_cfg;
798 mutex_lock(&mvm->mutex);
800 pos += scnprintf(buf + pos, bufsz - pos, "burst_period = %d\n",
801 le16_to_cpu(cmd->burst_period));
802 pos += scnprintf(buf + pos, bufsz - pos, "burst_duration = %d\n",
803 cmd->burst_duration);
804 pos += scnprintf(buf + pos, bufsz - pos, "bandwidth = %d\n",
806 pos += scnprintf(buf + pos, bufsz - pos, "channel_num = %d\n",
808 pos += scnprintf(buf + pos, bufsz - pos, "ctrl_ch_position = 0x%x\n",
809 cmd->ctrl_ch_position);
810 pos += scnprintf(buf + pos, bufsz - pos, "bssid = %pM\n",
812 pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %d\n",
814 pos += scnprintf(buf + pos, bufsz - pos, "num_of_burst_exp = %d\n",
815 cmd->num_of_burst_exp);
816 pos += scnprintf(buf + pos, bufsz - pos, "rate = %d\n", cmd->rate);
817 pos += scnprintf(buf + pos, bufsz - pos, "abort_responder = %d\n",
818 cmd->abort_responder);
819 pos += scnprintf(buf + pos, bufsz - pos, "get_ch_est = %d\n",
821 pos += scnprintf(buf + pos, bufsz - pos, "recv_sta_req_params = %d\n",
822 cmd->recv_sta_req_params);
823 pos += scnprintf(buf + pos, bufsz - pos, "ftm_per_burst = %d\n",
825 pos += scnprintf(buf + pos, bufsz - pos, "ftm_resp_ts_avail = %d\n",
826 cmd->ftm_resp_ts_avail);
827 pos += scnprintf(buf + pos, bufsz - pos, "asap_mode = %d\n",
829 pos += scnprintf(buf + pos, bufsz - pos,
830 "tsf_timer_offset_msecs = %d\n",
831 le16_to_cpu(cmd->tsf_timer_offset_msecs));
832 pos += scnprintf(buf + pos, bufsz - pos, "toa_offset = %d\n",
833 le16_to_cpu(cmd->toa_offset));
835 mutex_unlock(&mvm->mutex);
837 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
840 static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif,
841 char *buf, size_t count,
844 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
845 struct iwl_mvm *mvm = mvmvif->mvm;
850 mutex_lock(&mvm->mutex);
852 data = iwl_dbgfs_is_match("request_id=", buf);
854 ret = kstrtou32(data, 10, &value);
856 mvm->tof_data.range_req.request_id = value;
860 data = iwl_dbgfs_is_match("initiator=", buf);
862 ret = kstrtou32(data, 10, &value);
864 mvm->tof_data.range_req.initiator = value;
868 data = iwl_dbgfs_is_match("one_sided_los_disable=", buf);
870 ret = kstrtou32(data, 10, &value);
872 mvm->tof_data.range_req.one_sided_los_disable = value;
876 data = iwl_dbgfs_is_match("req_timeout=", buf);
878 ret = kstrtou32(data, 10, &value);
880 mvm->tof_data.range_req.req_timeout = value;
884 data = iwl_dbgfs_is_match("report_policy=", buf);
886 ret = kstrtou32(data, 10, &value);
888 mvm->tof_data.range_req.report_policy = value;
892 data = iwl_dbgfs_is_match("macaddr_random=", buf);
894 ret = kstrtou32(data, 10, &value);
896 mvm->tof_data.range_req.macaddr_random = value;
900 data = iwl_dbgfs_is_match("num_of_ap=", buf);
902 ret = kstrtou32(data, 10, &value);
904 mvm->tof_data.range_req.num_of_ap = value;
908 data = iwl_dbgfs_is_match("macaddr_template=", buf);
912 if (!mac_pton(data, mac)) {
916 memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN);
920 data = iwl_dbgfs_is_match("macaddr_mask=", buf);
924 if (!mac_pton(data, mac)) {
928 memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN);
932 data = iwl_dbgfs_is_match("ap=", buf);
934 struct iwl_tof_range_req_ap_entry ap = {};
935 int size = sizeof(struct iwl_tof_range_req_ap_entry);
940 if (sscanf(data, "%u %hhd %hhd %hhd"
941 "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
944 "%hhx %hhd %hhd %hhd",
945 &i, &ap.channel_num, &ap.bandwidth,
946 &ap.ctrl_ch_position,
947 mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5,
948 &ap.measure_type, &ap.num_of_bursts,
950 &ap.samples_per_burst, &ap.retries_per_sample,
951 &ap.tsf_delta, &ap.location_req, &ap.asap_mode,
952 &ap.enable_dyn_ack, &ap.rssi) != 20) {
956 if (i >= IWL_MVM_TOF_MAX_APS) {
957 IWL_ERR(mvm, "Invalid AP index %d\n", i);
962 ap.burst_period = cpu_to_le16(burst_period);
964 memcpy(&mvm->tof_data.range_req.ap[i], &ap, size);
968 data = iwl_dbgfs_is_match("send_range_request=", buf);
970 ret = kstrtou32(data, 10, &value);
971 if (ret == 0 && value)
972 ret = iwl_mvm_tof_range_request_cmd(mvm, vif);
978 mutex_unlock(&mvm->mutex);
982 static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file,
983 char __user *user_buf,
984 size_t count, loff_t *ppos)
986 struct ieee80211_vif *vif = file->private_data;
987 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
988 struct iwl_mvm *mvm = mvmvif->mvm;
991 const size_t bufsz = sizeof(buf);
992 struct iwl_tof_range_req_cmd *cmd;
995 cmd = &mvm->tof_data.range_req;
997 mutex_lock(&mvm->mutex);
999 pos += scnprintf(buf + pos, bufsz - pos, "request_id= %d\n",
1001 pos += scnprintf(buf + pos, bufsz - pos, "initiator= %d\n",
1003 pos += scnprintf(buf + pos, bufsz - pos, "one_sided_los_disable = %d\n",
1004 cmd->one_sided_los_disable);
1005 pos += scnprintf(buf + pos, bufsz - pos, "req_timeout= %d\n",
1007 pos += scnprintf(buf + pos, bufsz - pos, "report_policy= %d\n",
1008 cmd->report_policy);
1009 pos += scnprintf(buf + pos, bufsz - pos, "macaddr_random= %d\n",
1010 cmd->macaddr_random);
1011 pos += scnprintf(buf + pos, bufsz - pos, "macaddr_template= %pM\n",
1012 cmd->macaddr_template);
1013 pos += scnprintf(buf + pos, bufsz - pos, "macaddr_mask= %pM\n",
1015 pos += scnprintf(buf + pos, bufsz - pos, "num_of_ap= %d\n",
1017 for (i = 0; i < cmd->num_of_ap; i++) {
1018 struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i];
1020 pos += scnprintf(buf + pos, bufsz - pos,
1021 "ap %.2d: channel_num=%hhd bw=%hhd"
1022 " control=%hhd bssid=%pM type=%hhd"
1023 " num_of_bursts=%hhd burst_period=%hd ftm=%hhd"
1024 " retries=%hhd tsf_delta=%d"
1025 " tsf_delta_direction=%hhd location_req=0x%hhx "
1026 " asap=%hhd enable=%hhd rssi=%hhd\n",
1027 i, ap->channel_num, ap->bandwidth,
1028 ap->ctrl_ch_position, ap->bssid,
1029 ap->measure_type, ap->num_of_bursts,
1030 ap->burst_period, ap->samples_per_burst,
1031 ap->retries_per_sample, ap->tsf_delta,
1032 ap->tsf_delta_direction,
1033 ap->location_req, ap->asap_mode,
1034 ap->enable_dyn_ack, ap->rssi);
1037 mutex_unlock(&mvm->mutex);
1039 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1042 static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif,
1044 size_t count, loff_t *ppos)
1046 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1047 struct iwl_mvm *mvm = mvmvif->mvm;
1052 mutex_lock(&mvm->mutex);
1054 data = iwl_dbgfs_is_match("tsf_timer_offset_msec=", buf);
1056 ret = kstrtou32(data, 10, &value);
1058 mvm->tof_data.range_req_ext.tsf_timer_offset_msec =
1063 data = iwl_dbgfs_is_match("min_delta_ftm=", buf);
1065 ret = kstrtou32(data, 10, &value);
1067 mvm->tof_data.range_req_ext.min_delta_ftm = value;
1071 data = iwl_dbgfs_is_match("ftm_format_and_bw20M=", buf);
1073 ret = kstrtou32(data, 10, &value);
1075 mvm->tof_data.range_req_ext.ftm_format_and_bw20M =
1080 data = iwl_dbgfs_is_match("ftm_format_and_bw40M=", buf);
1082 ret = kstrtou32(data, 10, &value);
1084 mvm->tof_data.range_req_ext.ftm_format_and_bw40M =
1089 data = iwl_dbgfs_is_match("ftm_format_and_bw80M=", buf);
1091 ret = kstrtou32(data, 10, &value);
1093 mvm->tof_data.range_req_ext.ftm_format_and_bw80M =
1098 data = iwl_dbgfs_is_match("send_range_req_ext=", buf);
1100 ret = kstrtou32(data, 10, &value);
1101 if (ret == 0 && value)
1102 ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif);
1108 mutex_unlock(&mvm->mutex);
1109 return ret ?: count;
1112 static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file,
1113 char __user *user_buf,
1114 size_t count, loff_t *ppos)
1116 struct ieee80211_vif *vif = file->private_data;
1117 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1118 struct iwl_mvm *mvm = mvmvif->mvm;
1121 const size_t bufsz = sizeof(buf);
1122 struct iwl_tof_range_req_ext_cmd *cmd;
1124 cmd = &mvm->tof_data.range_req_ext;
1126 mutex_lock(&mvm->mutex);
1128 pos += scnprintf(buf + pos, bufsz - pos,
1129 "tsf_timer_offset_msec = %hd\n",
1130 cmd->tsf_timer_offset_msec);
1131 pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n",
1132 cmd->min_delta_ftm);
1133 pos += scnprintf(buf + pos, bufsz - pos,
1134 "ftm_format_and_bw20M = %hhd\n",
1135 cmd->ftm_format_and_bw20M);
1136 pos += scnprintf(buf + pos, bufsz - pos,
1137 "ftm_format_and_bw40M = %hhd\n",
1138 cmd->ftm_format_and_bw40M);
1139 pos += scnprintf(buf + pos, bufsz - pos,
1140 "ftm_format_and_bw80M = %hhd\n",
1141 cmd->ftm_format_and_bw80M);
1143 mutex_unlock(&mvm->mutex);
1144 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1147 static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif,
1149 size_t count, loff_t *ppos)
1151 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1152 struct iwl_mvm *mvm = mvmvif->mvm;
1154 int abort_id, ret = 0;
1157 mutex_lock(&mvm->mutex);
1159 data = iwl_dbgfs_is_match("abort_id=", buf);
1161 ret = kstrtou32(data, 10, &value);
1163 mvm->tof_data.last_abort_id = value;
1167 data = iwl_dbgfs_is_match("send_range_abort=", buf);
1169 ret = kstrtou32(data, 10, &value);
1170 if (ret == 0 && value) {
1171 abort_id = mvm->tof_data.last_abort_id;
1172 ret = iwl_mvm_tof_range_abort_cmd(mvm, abort_id);
1178 mutex_unlock(&mvm->mutex);
1179 return ret ?: count;
1182 static ssize_t iwl_dbgfs_tof_range_abort_read(struct file *file,
1183 char __user *user_buf,
1184 size_t count, loff_t *ppos)
1186 struct ieee80211_vif *vif = file->private_data;
1187 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1188 struct iwl_mvm *mvm = mvmvif->mvm;
1191 const size_t bufsz = sizeof(buf);
1194 mutex_lock(&mvm->mutex);
1195 last_abort_id = mvm->tof_data.last_abort_id;
1196 mutex_unlock(&mvm->mutex);
1198 pos += scnprintf(buf + pos, bufsz - pos, "last_abort_id = %d\n",
1200 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1203 static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file,
1204 char __user *user_buf,
1205 size_t count, loff_t *ppos)
1207 struct ieee80211_vif *vif = file->private_data;
1208 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1209 struct iwl_mvm *mvm = mvmvif->mvm;
1212 const size_t bufsz = sizeof(struct iwl_tof_range_rsp_ntfy) + 256;
1213 struct iwl_tof_range_rsp_ntfy *cmd;
1216 buf = kzalloc(bufsz, GFP_KERNEL);
1220 mutex_lock(&mvm->mutex);
1221 cmd = &mvm->tof_data.range_resp;
1223 pos += scnprintf(buf + pos, bufsz - pos, "request_id = %d\n",
1225 pos += scnprintf(buf + pos, bufsz - pos, "status = %d\n",
1226 cmd->request_status);
1227 pos += scnprintf(buf + pos, bufsz - pos, "last_in_batch = %d\n",
1228 cmd->last_in_batch);
1229 pos += scnprintf(buf + pos, bufsz - pos, "num_of_aps = %d\n",
1231 for (i = 0; i < cmd->num_of_aps; i++) {
1232 struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i];
1234 pos += scnprintf(buf + pos, bufsz - pos,
1235 "ap %.2d: bssid=%pM status=%hhd bw=%hhd"
1236 " rtt=%d rtt_var=%d rtt_spread=%d"
1237 " rssi=%hhd rssi_spread=%hhd"
1238 " range=%d range_var=%d"
1240 i, ap->bssid, ap->measure_status,
1242 ap->rtt, ap->rtt_variance, ap->rtt_spread,
1243 ap->rssi, ap->rssi_spread, ap->range,
1244 ap->range_variance, ap->timestamp);
1246 mutex_unlock(&mvm->mutex);
1248 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1253 static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
1254 size_t count, loff_t *ppos)
1256 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1257 struct iwl_mvm *mvm = mvmvif->mvm;
1261 ret = kstrtou8(buf, 0, &value);
1267 mutex_lock(&mvm->mutex);
1268 iwl_mvm_update_low_latency(mvm, vif, value);
1269 mutex_unlock(&mvm->mutex);
1274 static ssize_t iwl_dbgfs_low_latency_read(struct file *file,
1275 char __user *user_buf,
1276 size_t count, loff_t *ppos)
1278 struct ieee80211_vif *vif = file->private_data;
1279 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1282 buf[0] = mvmvif->low_latency ? '1' : '0';
1284 return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
1287 static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file,
1288 char __user *user_buf,
1289 size_t count, loff_t *ppos)
1291 struct ieee80211_vif *vif = file->private_data;
1292 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1296 len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid);
1297 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1300 static ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif,
1301 char *buf, size_t count,
1304 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1305 struct iwl_mvm *mvm = mvmvif->mvm;
1308 mutex_lock(&mvm->mutex);
1309 ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid);
1310 mutex_unlock(&mvm->mutex);
1312 return ret ? count : -EINVAL;
1315 static ssize_t iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif *vif, char *buf,
1316 size_t count, loff_t *ppos)
1318 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1319 struct iwl_mvm *mvm = mvmvif->mvm;
1320 struct ieee80211_chanctx_conf *chanctx_conf;
1321 struct iwl_mvm_phy_ctxt *phy_ctxt;
1325 ret = kstrtou16(buf, 0, &value);
1329 mutex_lock(&mvm->mutex);
1332 chanctx_conf = rcu_dereference(vif->chanctx_conf);
1333 /* make sure the channel context is assigned */
1334 if (!chanctx_conf) {
1336 mutex_unlock(&mvm->mutex);
1340 phy_ctxt = &mvm->phy_ctxts[*(u16 *)chanctx_conf->drv_priv];
1343 mvm->dbgfs_rx_phyinfo = value;
1345 ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chanctx_conf->min_def,
1346 chanctx_conf->rx_chains_static,
1347 chanctx_conf->rx_chains_dynamic);
1348 mutex_unlock(&mvm->mutex);
1350 return ret ?: count;
1353 static ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file,
1354 char __user *user_buf,
1355 size_t count, loff_t *ppos)
1357 struct ieee80211_vif *vif = file->private_data;
1358 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1361 snprintf(buf, sizeof(buf), "0x%04x\n", mvmvif->mvm->dbgfs_rx_phyinfo);
1363 return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf));
1366 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1367 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1368 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1369 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1370 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
1371 if (!debugfs_create_file(#name, mode, parent, vif, \
1372 &iwl_dbgfs_##name##_ops)) \
1376 MVM_DEBUGFS_READ_FILE_OPS(mac_params);
1377 MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
1378 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
1379 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
1380 MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
1381 MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
1382 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
1383 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable, 32);
1384 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request, 512);
1385 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32);
1386 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32);
1387 MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
1388 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
1390 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1392 struct dentry *dbgfs_dir = vif->debugfs_dir;
1393 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1397 * Check if debugfs directory already exist before creating it.
1398 * This may happen when, for example, resetting hw or suspend-resume
1400 if (!dbgfs_dir || mvmvif->dbgfs_dir)
1403 mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
1405 if (!mvmvif->dbgfs_dir) {
1406 IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
1407 dbgfs_dir->d_name.name);
1411 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
1412 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
1413 (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
1414 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
1415 MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
1418 MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, S_IRUSR);
1419 MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR);
1420 MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir,
1422 MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir,
1424 MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir,
1427 if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
1428 mvmvif == mvm->bf_allowed_vif)
1429 MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir,
1432 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT) &&
1433 !vif->p2p && (vif->type != NL80211_IFTYPE_P2P_DEVICE)) {
1434 if (IWL_MVM_TOF_IS_RESPONDER && vif->type == NL80211_IFTYPE_AP)
1435 MVM_DEBUGFS_ADD_FILE_VIF(tof_responder_params,
1439 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_request, mvmvif->dbgfs_dir,
1441 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_req_ext, mvmvif->dbgfs_dir,
1443 MVM_DEBUGFS_ADD_FILE_VIF(tof_enable, mvmvif->dbgfs_dir,
1445 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_abort, mvmvif->dbgfs_dir,
1447 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_response, mvmvif->dbgfs_dir,
1452 * Create symlink for convenience pointing to interface specific
1453 * debugfs entries for the driver. For example, under
1454 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1456 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1458 snprintf(buf, 100, "../../../%s/%s/%s/%s",
1459 dbgfs_dir->d_parent->d_parent->d_name.name,
1460 dbgfs_dir->d_parent->d_name.name,
1461 dbgfs_dir->d_name.name,
1462 mvmvif->dbgfs_dir->d_name.name);
1464 mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
1465 mvm->debugfs_dir, buf);
1466 if (!mvmvif->dbgfs_slink)
1467 IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
1468 dbgfs_dir->d_name.name);
1471 IWL_ERR(mvm, "Can't create debugfs entity\n");
1474 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1476 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1478 debugfs_remove(mvmvif->dbgfs_slink);
1479 mvmvif->dbgfs_slink = NULL;
1481 debugfs_remove_recursive(mvmvif->dbgfs_dir);
1482 mvmvif->dbgfs_dir = NULL;