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 <linuxwifi@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
;