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
10 * Copyright(c) 2016 Intel Deutschland GmbH
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.
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.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
26 * The full GNU General Public License is included in this distribution
27 * in the file called COPYING.
29 * Contact Information:
30 * Intel Linux Wireless <linuxwifi@intel.com>
31 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
35 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
36 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
37 * Copyright(c) 2016 Intel Deutschland GmbH
38 * All rights reserved.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
44 * * Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * * Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in
48 * the documentation and/or other materials provided with the
50 * * Neither the name Intel Corporation nor the names of its
51 * contributors may be used to endorse or promote products derived
52 * from this software without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
55 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
56 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
57 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
58 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
59 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
60 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
61 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
62 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
63 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
64 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66 *****************************************************************************/
68 #include "fw-api-tof.h"
71 static void iwl_dbgfs_update_pm(struct iwl_mvm
*mvm
,
72 struct ieee80211_vif
*vif
,
73 enum iwl_dbgfs_pm_mask param
, int val
)
75 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
76 struct iwl_dbgfs_pm
*dbgfs_pm
= &mvmvif
->dbgfs_pm
;
78 dbgfs_pm
->mask
|= param
;
81 case MVM_DEBUGFS_PM_KEEP_ALIVE
: {
82 int dtimper
= vif
->bss_conf
.dtim_period
?: 1;
83 int dtimper_msec
= dtimper
* vif
->bss_conf
.beacon_int
;
85 IWL_DEBUG_POWER(mvm
, "debugfs: set keep_alive= %d sec\n", val
);
86 if (val
* MSEC_PER_SEC
< 3 * dtimper_msec
)
88 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
89 val
* MSEC_PER_SEC
, 3 * dtimper_msec
);
90 dbgfs_pm
->keep_alive_seconds
= val
;
93 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM
:
94 IWL_DEBUG_POWER(mvm
, "skip_over_dtim %s\n",
95 val
? "enabled" : "disabled");
96 dbgfs_pm
->skip_over_dtim
= val
;
98 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
:
99 IWL_DEBUG_POWER(mvm
, "skip_dtim_periods=%d\n", val
);
100 dbgfs_pm
->skip_dtim_periods
= val
;
102 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
:
103 IWL_DEBUG_POWER(mvm
, "rx_data_timeout=%d\n", val
);
104 dbgfs_pm
->rx_data_timeout
= val
;
106 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
:
107 IWL_DEBUG_POWER(mvm
, "tx_data_timeout=%d\n", val
);
108 dbgfs_pm
->tx_data_timeout
= val
;
110 case MVM_DEBUGFS_PM_LPRX_ENA
:
111 IWL_DEBUG_POWER(mvm
, "lprx %s\n", val
? "enabled" : "disabled");
112 dbgfs_pm
->lprx_ena
= val
;
114 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
:
115 IWL_DEBUG_POWER(mvm
, "lprx_rssi_threshold=%d\n", val
);
116 dbgfs_pm
->lprx_rssi_threshold
= val
;
118 case MVM_DEBUGFS_PM_SNOOZE_ENABLE
:
119 IWL_DEBUG_POWER(mvm
, "snooze_enable=%d\n", val
);
120 dbgfs_pm
->snooze_ena
= val
;
122 case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
:
123 IWL_DEBUG_POWER(mvm
, "uapsd_misbehaving_enable=%d\n", val
);
124 dbgfs_pm
->uapsd_misbehaving
= val
;
126 case MVM_DEBUGFS_PM_USE_PS_POLL
:
127 IWL_DEBUG_POWER(mvm
, "use_ps_poll=%d\n", val
);
128 dbgfs_pm
->use_ps_poll
= val
;
133 static ssize_t
iwl_dbgfs_pm_params_write(struct ieee80211_vif
*vif
, char *buf
,
134 size_t count
, loff_t
*ppos
)
136 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
137 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
138 enum iwl_dbgfs_pm_mask param
;
141 if (!strncmp("keep_alive=", buf
, 11)) {
142 if (sscanf(buf
+ 11, "%d", &val
) != 1)
144 param
= MVM_DEBUGFS_PM_KEEP_ALIVE
;
145 } else if (!strncmp("skip_over_dtim=", buf
, 15)) {
146 if (sscanf(buf
+ 15, "%d", &val
) != 1)
148 param
= MVM_DEBUGFS_PM_SKIP_OVER_DTIM
;
149 } else if (!strncmp("skip_dtim_periods=", buf
, 18)) {
150 if (sscanf(buf
+ 18, "%d", &val
) != 1)
152 param
= MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
;
153 } else if (!strncmp("rx_data_timeout=", buf
, 16)) {
154 if (sscanf(buf
+ 16, "%d", &val
) != 1)
156 param
= MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
;
157 } else if (!strncmp("tx_data_timeout=", buf
, 16)) {
158 if (sscanf(buf
+ 16, "%d", &val
) != 1)
160 param
= MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
;
161 } else if (!strncmp("lprx=", buf
, 5)) {
162 if (sscanf(buf
+ 5, "%d", &val
) != 1)
164 param
= MVM_DEBUGFS_PM_LPRX_ENA
;
165 } else if (!strncmp("lprx_rssi_threshold=", buf
, 20)) {
166 if (sscanf(buf
+ 20, "%d", &val
) != 1)
168 if (val
> POWER_LPRX_RSSI_THRESHOLD_MAX
|| val
<
169 POWER_LPRX_RSSI_THRESHOLD_MIN
)
171 param
= MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
;
172 } else if (!strncmp("snooze_enable=", buf
, 14)) {
173 if (sscanf(buf
+ 14, "%d", &val
) != 1)
175 param
= MVM_DEBUGFS_PM_SNOOZE_ENABLE
;
176 } else if (!strncmp("uapsd_misbehaving=", buf
, 18)) {
177 if (sscanf(buf
+ 18, "%d", &val
) != 1)
179 param
= MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
;
180 } else if (!strncmp("use_ps_poll=", buf
, 12)) {
181 if (sscanf(buf
+ 12, "%d", &val
) != 1)
183 param
= MVM_DEBUGFS_PM_USE_PS_POLL
;
188 mutex_lock(&mvm
->mutex
);
189 iwl_dbgfs_update_pm(mvm
, vif
, param
, val
);
190 ret
= iwl_mvm_power_update_mac(mvm
);
191 mutex_unlock(&mvm
->mutex
);
196 static ssize_t
iwl_dbgfs_tx_pwr_lmt_read(struct file
*file
,
197 char __user
*user_buf
,
198 size_t count
, loff_t
*ppos
)
200 struct ieee80211_vif
*vif
= file
->private_data
;
202 int bufsz
= sizeof(buf
);
205 pos
= scnprintf(buf
, bufsz
, "bss limit = %d\n",
206 vif
->bss_conf
.txpower
);
208 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
211 static ssize_t
iwl_dbgfs_pm_params_read(struct file
*file
,
212 char __user
*user_buf
,
213 size_t count
, loff_t
*ppos
)
215 struct ieee80211_vif
*vif
= file
->private_data
;
216 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
217 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
219 int bufsz
= sizeof(buf
);
222 pos
= iwl_mvm_power_mac_dbgfs_read(mvm
, vif
, buf
, bufsz
);
224 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
227 static ssize_t
iwl_dbgfs_mac_params_read(struct file
*file
,
228 char __user
*user_buf
,
229 size_t count
, loff_t
*ppos
)
231 struct ieee80211_vif
*vif
= file
->private_data
;
232 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
233 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
235 struct ieee80211_chanctx_conf
*chanctx_conf
;
237 int bufsz
= sizeof(buf
);
241 mutex_lock(&mvm
->mutex
);
243 ap_sta_id
= mvmvif
->ap_sta_id
;
245 switch (ieee80211_vif_type_p2p(vif
)) {
246 case NL80211_IFTYPE_ADHOC
:
247 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: ibss\n");
249 case NL80211_IFTYPE_STATION
:
250 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: bss\n");
252 case NL80211_IFTYPE_AP
:
253 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: ap\n");
255 case NL80211_IFTYPE_P2P_CLIENT
:
256 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p client\n");
258 case NL80211_IFTYPE_P2P_GO
:
259 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p go\n");
261 case NL80211_IFTYPE_P2P_DEVICE
:
262 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p dev\n");
268 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "mac id/color: %d / %d\n",
269 mvmvif
->id
, mvmvif
->color
);
270 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bssid: %pM\n",
271 vif
->bss_conf
.bssid
);
272 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "QoS:\n");
273 for (i
= 0; i
< ARRAY_SIZE(mvmvif
->queue_params
); i
++)
274 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
275 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
276 i
, mvmvif
->queue_params
[i
].txop
,
277 mvmvif
->queue_params
[i
].cw_min
,
278 mvmvif
->queue_params
[i
].cw_max
,
279 mvmvif
->queue_params
[i
].aifs
,
280 mvmvif
->queue_params
[i
].uapsd
);
282 if (vif
->type
== NL80211_IFTYPE_STATION
&&
283 ap_sta_id
!= IWL_MVM_STATION_COUNT
) {
284 struct ieee80211_sta
*sta
;
286 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[ap_sta_id
],
287 lockdep_is_held(&mvm
->mutex
));
288 if (!IS_ERR_OR_NULL(sta
)) {
289 struct iwl_mvm_sta
*mvm_sta
= iwl_mvm_sta_from_mac80211(sta
);
291 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
292 "ap_sta_id %d - reduced Tx power %d\n",
294 mvm_sta
->bt_reduced_txpower
);
299 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
301 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
302 "idle rx chains %d, active rx chains: %d\n",
303 chanctx_conf
->rx_chains_static
,
304 chanctx_conf
->rx_chains_dynamic
);
307 mutex_unlock(&mvm
->mutex
);
309 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
312 static void iwl_dbgfs_update_bf(struct ieee80211_vif
*vif
,
313 enum iwl_dbgfs_bf_mask param
, int value
)
315 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
316 struct iwl_dbgfs_bf
*dbgfs_bf
= &mvmvif
->dbgfs_bf
;
318 dbgfs_bf
->mask
|= param
;
321 case MVM_DEBUGFS_BF_ENERGY_DELTA
:
322 dbgfs_bf
->bf_energy_delta
= value
;
324 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
325 dbgfs_bf
->bf_roaming_energy_delta
= value
;
327 case MVM_DEBUGFS_BF_ROAMING_STATE
:
328 dbgfs_bf
->bf_roaming_state
= value
;
330 case MVM_DEBUGFS_BF_TEMP_THRESHOLD
:
331 dbgfs_bf
->bf_temp_threshold
= value
;
333 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER
:
334 dbgfs_bf
->bf_temp_fast_filter
= value
;
336 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
:
337 dbgfs_bf
->bf_temp_slow_filter
= value
;
339 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
340 dbgfs_bf
->bf_enable_beacon_filter
= value
;
342 case MVM_DEBUGFS_BF_DEBUG_FLAG
:
343 dbgfs_bf
->bf_debug_flag
= value
;
345 case MVM_DEBUGFS_BF_ESCAPE_TIMER
:
346 dbgfs_bf
->bf_escape_timer
= value
;
348 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
349 dbgfs_bf
->ba_enable_beacon_abort
= value
;
351 case MVM_DEBUGFS_BA_ESCAPE_TIMER
:
352 dbgfs_bf
->ba_escape_timer
= value
;
357 static ssize_t
iwl_dbgfs_bf_params_write(struct ieee80211_vif
*vif
, char *buf
,
358 size_t count
, loff_t
*ppos
)
360 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
361 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
362 enum iwl_dbgfs_bf_mask param
;
365 if (!strncmp("bf_energy_delta=", buf
, 16)) {
366 if (sscanf(buf
+16, "%d", &value
) != 1)
368 if (value
< IWL_BF_ENERGY_DELTA_MIN
||
369 value
> IWL_BF_ENERGY_DELTA_MAX
)
371 param
= MVM_DEBUGFS_BF_ENERGY_DELTA
;
372 } else if (!strncmp("bf_roaming_energy_delta=", buf
, 24)) {
373 if (sscanf(buf
+24, "%d", &value
) != 1)
375 if (value
< IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
376 value
> IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
378 param
= MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
379 } else if (!strncmp("bf_roaming_state=", buf
, 17)) {
380 if (sscanf(buf
+17, "%d", &value
) != 1)
382 if (value
< IWL_BF_ROAMING_STATE_MIN
||
383 value
> IWL_BF_ROAMING_STATE_MAX
)
385 param
= MVM_DEBUGFS_BF_ROAMING_STATE
;
386 } else if (!strncmp("bf_temp_threshold=", buf
, 18)) {
387 if (sscanf(buf
+18, "%d", &value
) != 1)
389 if (value
< IWL_BF_TEMP_THRESHOLD_MIN
||
390 value
> IWL_BF_TEMP_THRESHOLD_MAX
)
392 param
= MVM_DEBUGFS_BF_TEMP_THRESHOLD
;
393 } else if (!strncmp("bf_temp_fast_filter=", buf
, 20)) {
394 if (sscanf(buf
+20, "%d", &value
) != 1)
396 if (value
< IWL_BF_TEMP_FAST_FILTER_MIN
||
397 value
> IWL_BF_TEMP_FAST_FILTER_MAX
)
399 param
= MVM_DEBUGFS_BF_TEMP_FAST_FILTER
;
400 } else if (!strncmp("bf_temp_slow_filter=", buf
, 20)) {
401 if (sscanf(buf
+20, "%d", &value
) != 1)
403 if (value
< IWL_BF_TEMP_SLOW_FILTER_MIN
||
404 value
> IWL_BF_TEMP_SLOW_FILTER_MAX
)
406 param
= MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
;
407 } else if (!strncmp("bf_enable_beacon_filter=", buf
, 24)) {
408 if (sscanf(buf
+24, "%d", &value
) != 1)
410 if (value
< 0 || value
> 1)
412 param
= MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
413 } else if (!strncmp("bf_debug_flag=", buf
, 14)) {
414 if (sscanf(buf
+14, "%d", &value
) != 1)
416 if (value
< 0 || value
> 1)
418 param
= MVM_DEBUGFS_BF_DEBUG_FLAG
;
419 } else if (!strncmp("bf_escape_timer=", buf
, 16)) {
420 if (sscanf(buf
+16, "%d", &value
) != 1)
422 if (value
< IWL_BF_ESCAPE_TIMER_MIN
||
423 value
> IWL_BF_ESCAPE_TIMER_MAX
)
425 param
= MVM_DEBUGFS_BF_ESCAPE_TIMER
;
426 } else if (!strncmp("ba_escape_timer=", buf
, 16)) {
427 if (sscanf(buf
+16, "%d", &value
) != 1)
429 if (value
< IWL_BA_ESCAPE_TIMER_MIN
||
430 value
> IWL_BA_ESCAPE_TIMER_MAX
)
432 param
= MVM_DEBUGFS_BA_ESCAPE_TIMER
;
433 } else if (!strncmp("ba_enable_beacon_abort=", buf
, 23)) {
434 if (sscanf(buf
+23, "%d", &value
) != 1)
436 if (value
< 0 || value
> 1)
438 param
= MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
443 mutex_lock(&mvm
->mutex
);
444 iwl_dbgfs_update_bf(vif
, param
, value
);
445 if (param
== MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&& !value
)
446 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
, 0);
448 ret
= iwl_mvm_enable_beacon_filter(mvm
, vif
, 0);
449 mutex_unlock(&mvm
->mutex
);
454 static ssize_t
iwl_dbgfs_bf_params_read(struct file
*file
,
455 char __user
*user_buf
,
456 size_t count
, loff_t
*ppos
)
458 struct ieee80211_vif
*vif
= file
->private_data
;
459 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
462 const size_t bufsz
= sizeof(buf
);
463 struct iwl_beacon_filter_cmd cmd
= {
464 IWL_BF_CMD_CONFIG_DEFAULTS
,
465 .bf_enable_beacon_filter
=
466 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
),
467 .ba_enable_beacon_abort
=
468 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
),
471 iwl_mvm_beacon_filter_debugfs_parameters(vif
, &cmd
);
472 if (mvmvif
->bf_data
.bf_enabled
)
473 cmd
.bf_enable_beacon_filter
= cpu_to_le32(1);
475 cmd
.bf_enable_beacon_filter
= 0;
477 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_energy_delta = %d\n",
478 le32_to_cpu(cmd
.bf_energy_delta
));
479 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_energy_delta = %d\n",
480 le32_to_cpu(cmd
.bf_roaming_energy_delta
));
481 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_state = %d\n",
482 le32_to_cpu(cmd
.bf_roaming_state
));
483 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_threshold = %d\n",
484 le32_to_cpu(cmd
.bf_temp_threshold
));
485 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_fast_filter = %d\n",
486 le32_to_cpu(cmd
.bf_temp_fast_filter
));
487 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_slow_filter = %d\n",
488 le32_to_cpu(cmd
.bf_temp_slow_filter
));
489 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_enable_beacon_filter = %d\n",
490 le32_to_cpu(cmd
.bf_enable_beacon_filter
));
491 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_debug_flag = %d\n",
492 le32_to_cpu(cmd
.bf_debug_flag
));
493 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_escape_timer = %d\n",
494 le32_to_cpu(cmd
.bf_escape_timer
));
495 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_escape_timer = %d\n",
496 le32_to_cpu(cmd
.ba_escape_timer
));
497 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_enable_beacon_abort = %d\n",
498 le32_to_cpu(cmd
.ba_enable_beacon_abort
));
500 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
503 static inline char *iwl_dbgfs_is_match(char *name
, char *buf
)
505 int len
= strlen(name
);
507 return !strncmp(name
, buf
, len
) ? buf
+ len
: NULL
;
510 static ssize_t
iwl_dbgfs_tof_enable_write(struct ieee80211_vif
*vif
,
512 size_t count
, loff_t
*ppos
)
514 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
515 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
520 mutex_lock(&mvm
->mutex
);
522 data
= iwl_dbgfs_is_match("tof_disabled=", buf
);
524 ret
= kstrtou32(data
, 10, &value
);
526 mvm
->tof_data
.tof_cfg
.tof_disabled
= value
;
530 data
= iwl_dbgfs_is_match("one_sided_disabled=", buf
);
532 ret
= kstrtou32(data
, 10, &value
);
534 mvm
->tof_data
.tof_cfg
.one_sided_disabled
= value
;
538 data
= iwl_dbgfs_is_match("is_debug_mode=", buf
);
540 ret
= kstrtou32(data
, 10, &value
);
542 mvm
->tof_data
.tof_cfg
.is_debug_mode
= value
;
546 data
= iwl_dbgfs_is_match("is_buf=", buf
);
548 ret
= kstrtou32(data
, 10, &value
);
550 mvm
->tof_data
.tof_cfg
.is_buf_required
= value
;
554 data
= iwl_dbgfs_is_match("send_tof_cfg=", buf
);
556 ret
= kstrtou32(data
, 10, &value
);
557 if (ret
== 0 && value
) {
558 ret
= iwl_mvm_tof_config_cmd(mvm
);
564 mutex_unlock(&mvm
->mutex
);
569 static ssize_t
iwl_dbgfs_tof_enable_read(struct file
*file
,
570 char __user
*user_buf
,
571 size_t count
, loff_t
*ppos
)
573 struct ieee80211_vif
*vif
= file
->private_data
;
574 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
575 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
578 const size_t bufsz
= sizeof(buf
);
579 struct iwl_tof_config_cmd
*cmd
;
581 cmd
= &mvm
->tof_data
.tof_cfg
;
583 mutex_lock(&mvm
->mutex
);
585 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "tof_disabled = %d\n",
587 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "one_sided_disabled = %d\n",
588 cmd
->one_sided_disabled
);
589 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "is_debug_mode = %d\n",
591 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "is_buf_required = %d\n",
592 cmd
->is_buf_required
);
594 mutex_unlock(&mvm
->mutex
);
596 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
599 static ssize_t
iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif
*vif
,
601 size_t count
, loff_t
*ppos
)
603 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
604 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
609 mutex_lock(&mvm
->mutex
);
611 data
= iwl_dbgfs_is_match("burst_period=", buf
);
613 ret
= kstrtou32(data
, 10, &value
);
615 mvm
->tof_data
.responder_cfg
.burst_period
=
620 data
= iwl_dbgfs_is_match("min_delta_ftm=", buf
);
622 ret
= kstrtou32(data
, 10, &value
);
624 mvm
->tof_data
.responder_cfg
.min_delta_ftm
= value
;
628 data
= iwl_dbgfs_is_match("burst_duration=", buf
);
630 ret
= kstrtou32(data
, 10, &value
);
632 mvm
->tof_data
.responder_cfg
.burst_duration
= value
;
636 data
= iwl_dbgfs_is_match("num_of_burst_exp=", buf
);
638 ret
= kstrtou32(data
, 10, &value
);
640 mvm
->tof_data
.responder_cfg
.num_of_burst_exp
= value
;
644 data
= iwl_dbgfs_is_match("abort_responder=", buf
);
646 ret
= kstrtou32(data
, 10, &value
);
648 mvm
->tof_data
.responder_cfg
.abort_responder
= value
;
652 data
= iwl_dbgfs_is_match("get_ch_est=", buf
);
654 ret
= kstrtou32(data
, 10, &value
);
656 mvm
->tof_data
.responder_cfg
.get_ch_est
= value
;
660 data
= iwl_dbgfs_is_match("recv_sta_req_params=", buf
);
662 ret
= kstrtou32(data
, 10, &value
);
664 mvm
->tof_data
.responder_cfg
.recv_sta_req_params
= value
;
668 data
= iwl_dbgfs_is_match("channel_num=", buf
);
670 ret
= kstrtou32(data
, 10, &value
);
672 mvm
->tof_data
.responder_cfg
.channel_num
= value
;
676 data
= iwl_dbgfs_is_match("bandwidth=", buf
);
678 ret
= kstrtou32(data
, 10, &value
);
680 mvm
->tof_data
.responder_cfg
.bandwidth
= value
;
684 data
= iwl_dbgfs_is_match("rate=", buf
);
686 ret
= kstrtou32(data
, 10, &value
);
688 mvm
->tof_data
.responder_cfg
.rate
= value
;
692 data
= iwl_dbgfs_is_match("bssid=", buf
);
694 u8
*mac
= mvm
->tof_data
.responder_cfg
.bssid
;
696 if (!mac_pton(data
, mac
)) {
702 data
= iwl_dbgfs_is_match("tsf_timer_offset_msecs=", buf
);
704 ret
= kstrtou32(data
, 10, &value
);
706 mvm
->tof_data
.responder_cfg
.tsf_timer_offset_msecs
=
711 data
= iwl_dbgfs_is_match("toa_offset=", buf
);
713 ret
= kstrtou32(data
, 10, &value
);
715 mvm
->tof_data
.responder_cfg
.toa_offset
=
720 data
= iwl_dbgfs_is_match("center_freq=", buf
);
722 struct iwl_tof_responder_config_cmd
*cmd
=
723 &mvm
->tof_data
.responder_cfg
;
725 ret
= kstrtou32(data
, 10, &value
);
726 if (ret
== 0 && value
) {
727 enum ieee80211_band band
= (cmd
->channel_num
<= 14) ?
728 IEEE80211_BAND_2GHZ
:
730 struct ieee80211_channel chn
= {
732 .center_freq
= ieee80211_channel_to_frequency(
733 cmd
->channel_num
, band
),
735 struct cfg80211_chan_def chandef
= {
738 ieee80211_channel_to_frequency(value
,
742 cmd
->ctrl_ch_position
= iwl_mvm_get_ctrl_pos(&chandef
);
747 data
= iwl_dbgfs_is_match("ftm_per_burst=", buf
);
749 ret
= kstrtou32(data
, 10, &value
);
751 mvm
->tof_data
.responder_cfg
.ftm_per_burst
= value
;
755 data
= iwl_dbgfs_is_match("ftm_resp_ts_avail=", buf
);
757 ret
= kstrtou32(data
, 10, &value
);
759 mvm
->tof_data
.responder_cfg
.ftm_resp_ts_avail
= value
;
763 data
= iwl_dbgfs_is_match("asap_mode=", buf
);
765 ret
= kstrtou32(data
, 10, &value
);
767 mvm
->tof_data
.responder_cfg
.asap_mode
= value
;
771 data
= iwl_dbgfs_is_match("send_responder_cfg=", buf
);
773 ret
= kstrtou32(data
, 10, &value
);
774 if (ret
== 0 && value
) {
775 ret
= iwl_mvm_tof_responder_cmd(mvm
, vif
);
781 mutex_unlock(&mvm
->mutex
);
786 static ssize_t
iwl_dbgfs_tof_responder_params_read(struct file
*file
,
787 char __user
*user_buf
,
788 size_t count
, loff_t
*ppos
)
790 struct ieee80211_vif
*vif
= file
->private_data
;
791 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
792 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
795 const size_t bufsz
= sizeof(buf
);
796 struct iwl_tof_responder_config_cmd
*cmd
;
798 cmd
= &mvm
->tof_data
.responder_cfg
;
800 mutex_lock(&mvm
->mutex
);
802 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "burst_period = %d\n",
803 le16_to_cpu(cmd
->burst_period
));
804 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "burst_duration = %d\n",
805 cmd
->burst_duration
);
806 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "bandwidth = %d\n",
808 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "channel_num = %d\n",
810 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "ctrl_ch_position = 0x%x\n",
811 cmd
->ctrl_ch_position
);
812 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "bssid = %pM\n",
814 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "min_delta_ftm = %d\n",
816 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "num_of_burst_exp = %d\n",
817 cmd
->num_of_burst_exp
);
818 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "rate = %d\n", cmd
->rate
);
819 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "abort_responder = %d\n",
820 cmd
->abort_responder
);
821 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "get_ch_est = %d\n",
823 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "recv_sta_req_params = %d\n",
824 cmd
->recv_sta_req_params
);
825 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "ftm_per_burst = %d\n",
827 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "ftm_resp_ts_avail = %d\n",
828 cmd
->ftm_resp_ts_avail
);
829 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "asap_mode = %d\n",
831 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
832 "tsf_timer_offset_msecs = %d\n",
833 le16_to_cpu(cmd
->tsf_timer_offset_msecs
));
834 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "toa_offset = %d\n",
835 le16_to_cpu(cmd
->toa_offset
));
837 mutex_unlock(&mvm
->mutex
);
839 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
842 static ssize_t
iwl_dbgfs_tof_range_request_write(struct ieee80211_vif
*vif
,
843 char *buf
, size_t count
,
846 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
847 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
852 mutex_lock(&mvm
->mutex
);
854 data
= iwl_dbgfs_is_match("request_id=", buf
);
856 ret
= kstrtou32(data
, 10, &value
);
858 mvm
->tof_data
.range_req
.request_id
= value
;
862 data
= iwl_dbgfs_is_match("initiator=", buf
);
864 ret
= kstrtou32(data
, 10, &value
);
866 mvm
->tof_data
.range_req
.initiator
= value
;
870 data
= iwl_dbgfs_is_match("one_sided_los_disable=", buf
);
872 ret
= kstrtou32(data
, 10, &value
);
874 mvm
->tof_data
.range_req
.one_sided_los_disable
= value
;
878 data
= iwl_dbgfs_is_match("req_timeout=", buf
);
880 ret
= kstrtou32(data
, 10, &value
);
882 mvm
->tof_data
.range_req
.req_timeout
= value
;
886 data
= iwl_dbgfs_is_match("report_policy=", buf
);
888 ret
= kstrtou32(data
, 10, &value
);
890 mvm
->tof_data
.range_req
.report_policy
= value
;
894 data
= iwl_dbgfs_is_match("macaddr_random=", buf
);
896 ret
= kstrtou32(data
, 10, &value
);
898 mvm
->tof_data
.range_req
.macaddr_random
= value
;
902 data
= iwl_dbgfs_is_match("num_of_ap=", buf
);
904 ret
= kstrtou32(data
, 10, &value
);
906 mvm
->tof_data
.range_req
.num_of_ap
= value
;
910 data
= iwl_dbgfs_is_match("macaddr_template=", buf
);
914 if (!mac_pton(data
, mac
)) {
918 memcpy(mvm
->tof_data
.range_req
.macaddr_template
, mac
, ETH_ALEN
);
922 data
= iwl_dbgfs_is_match("macaddr_mask=", buf
);
926 if (!mac_pton(data
, mac
)) {
930 memcpy(mvm
->tof_data
.range_req
.macaddr_mask
, mac
, ETH_ALEN
);
934 data
= iwl_dbgfs_is_match("ap=", buf
);
936 struct iwl_tof_range_req_ap_entry ap
= {};
937 int size
= sizeof(struct iwl_tof_range_req_ap_entry
);
942 if (sscanf(data
, "%u %hhd %hhd %hhd"
943 "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
946 "%hhx %hhd %hhd %hhd",
947 &i
, &ap
.channel_num
, &ap
.bandwidth
,
948 &ap
.ctrl_ch_position
,
949 mac
, mac
+ 1, mac
+ 2, mac
+ 3, mac
+ 4, mac
+ 5,
950 &ap
.measure_type
, &ap
.num_of_bursts
,
952 &ap
.samples_per_burst
, &ap
.retries_per_sample
,
953 &ap
.tsf_delta
, &ap
.location_req
, &ap
.asap_mode
,
954 &ap
.enable_dyn_ack
, &ap
.rssi
) != 20) {
958 if (i
>= IWL_MVM_TOF_MAX_APS
) {
959 IWL_ERR(mvm
, "Invalid AP index %d\n", i
);
964 ap
.burst_period
= cpu_to_le16(burst_period
);
966 memcpy(&mvm
->tof_data
.range_req
.ap
[i
], &ap
, size
);
970 data
= iwl_dbgfs_is_match("send_range_request=", buf
);
972 ret
= kstrtou32(data
, 10, &value
);
973 if (ret
== 0 && value
)
974 ret
= iwl_mvm_tof_range_request_cmd(mvm
, vif
);
980 mutex_unlock(&mvm
->mutex
);
984 static ssize_t
iwl_dbgfs_tof_range_request_read(struct file
*file
,
985 char __user
*user_buf
,
986 size_t count
, loff_t
*ppos
)
988 struct ieee80211_vif
*vif
= file
->private_data
;
989 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
990 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
993 const size_t bufsz
= sizeof(buf
);
994 struct iwl_tof_range_req_cmd
*cmd
;
997 cmd
= &mvm
->tof_data
.range_req
;
999 mutex_lock(&mvm
->mutex
);
1001 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "request_id= %d\n",
1003 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "initiator= %d\n",
1005 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "one_sided_los_disable = %d\n",
1006 cmd
->one_sided_los_disable
);
1007 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "req_timeout= %d\n",
1009 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "report_policy= %d\n",
1010 cmd
->report_policy
);
1011 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "macaddr_random= %d\n",
1012 cmd
->macaddr_random
);
1013 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "macaddr_template= %pM\n",
1014 cmd
->macaddr_template
);
1015 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "macaddr_mask= %pM\n",
1017 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "num_of_ap= %d\n",
1019 for (i
= 0; i
< cmd
->num_of_ap
; i
++) {
1020 struct iwl_tof_range_req_ap_entry
*ap
= &cmd
->ap
[i
];
1022 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1023 "ap %.2d: channel_num=%hhd bw=%hhd"
1024 " control=%hhd bssid=%pM type=%hhd"
1025 " num_of_bursts=%hhd burst_period=%hd ftm=%hhd"
1026 " retries=%hhd tsf_delta=%d"
1027 " tsf_delta_direction=%hhd location_req=0x%hhx "
1028 " asap=%hhd enable=%hhd rssi=%hhd\n",
1029 i
, ap
->channel_num
, ap
->bandwidth
,
1030 ap
->ctrl_ch_position
, ap
->bssid
,
1031 ap
->measure_type
, ap
->num_of_bursts
,
1032 ap
->burst_period
, ap
->samples_per_burst
,
1033 ap
->retries_per_sample
, ap
->tsf_delta
,
1034 ap
->tsf_delta_direction
,
1035 ap
->location_req
, ap
->asap_mode
,
1036 ap
->enable_dyn_ack
, ap
->rssi
);
1039 mutex_unlock(&mvm
->mutex
);
1041 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1044 static ssize_t
iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif
*vif
,
1046 size_t count
, loff_t
*ppos
)
1048 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1049 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1054 mutex_lock(&mvm
->mutex
);
1056 data
= iwl_dbgfs_is_match("tsf_timer_offset_msec=", buf
);
1058 ret
= kstrtou32(data
, 10, &value
);
1060 mvm
->tof_data
.range_req_ext
.tsf_timer_offset_msec
=
1065 data
= iwl_dbgfs_is_match("min_delta_ftm=", buf
);
1067 ret
= kstrtou32(data
, 10, &value
);
1069 mvm
->tof_data
.range_req_ext
.min_delta_ftm
= value
;
1073 data
= iwl_dbgfs_is_match("ftm_format_and_bw20M=", buf
);
1075 ret
= kstrtou32(data
, 10, &value
);
1077 mvm
->tof_data
.range_req_ext
.ftm_format_and_bw20M
=
1082 data
= iwl_dbgfs_is_match("ftm_format_and_bw40M=", buf
);
1084 ret
= kstrtou32(data
, 10, &value
);
1086 mvm
->tof_data
.range_req_ext
.ftm_format_and_bw40M
=
1091 data
= iwl_dbgfs_is_match("ftm_format_and_bw80M=", buf
);
1093 ret
= kstrtou32(data
, 10, &value
);
1095 mvm
->tof_data
.range_req_ext
.ftm_format_and_bw80M
=
1100 data
= iwl_dbgfs_is_match("send_range_req_ext=", buf
);
1102 ret
= kstrtou32(data
, 10, &value
);
1103 if (ret
== 0 && value
)
1104 ret
= iwl_mvm_tof_range_request_ext_cmd(mvm
, vif
);
1110 mutex_unlock(&mvm
->mutex
);
1111 return ret
?: count
;
1114 static ssize_t
iwl_dbgfs_tof_range_req_ext_read(struct file
*file
,
1115 char __user
*user_buf
,
1116 size_t count
, loff_t
*ppos
)
1118 struct ieee80211_vif
*vif
= file
->private_data
;
1119 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1120 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1123 const size_t bufsz
= sizeof(buf
);
1124 struct iwl_tof_range_req_ext_cmd
*cmd
;
1126 cmd
= &mvm
->tof_data
.range_req_ext
;
1128 mutex_lock(&mvm
->mutex
);
1130 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1131 "tsf_timer_offset_msec = %hd\n",
1132 cmd
->tsf_timer_offset_msec
);
1133 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "min_delta_ftm = %hhd\n",
1134 cmd
->min_delta_ftm
);
1135 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1136 "ftm_format_and_bw20M = %hhd\n",
1137 cmd
->ftm_format_and_bw20M
);
1138 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1139 "ftm_format_and_bw40M = %hhd\n",
1140 cmd
->ftm_format_and_bw40M
);
1141 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1142 "ftm_format_and_bw80M = %hhd\n",
1143 cmd
->ftm_format_and_bw80M
);
1145 mutex_unlock(&mvm
->mutex
);
1146 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1149 static ssize_t
iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif
*vif
,
1151 size_t count
, loff_t
*ppos
)
1153 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1154 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1156 int abort_id
, ret
= 0;
1159 mutex_lock(&mvm
->mutex
);
1161 data
= iwl_dbgfs_is_match("abort_id=", buf
);
1163 ret
= kstrtou32(data
, 10, &value
);
1165 mvm
->tof_data
.last_abort_id
= value
;
1169 data
= iwl_dbgfs_is_match("send_range_abort=", buf
);
1171 ret
= kstrtou32(data
, 10, &value
);
1172 if (ret
== 0 && value
) {
1173 abort_id
= mvm
->tof_data
.last_abort_id
;
1174 ret
= iwl_mvm_tof_range_abort_cmd(mvm
, abort_id
);
1180 mutex_unlock(&mvm
->mutex
);
1181 return ret
?: count
;
1184 static ssize_t
iwl_dbgfs_tof_range_abort_read(struct file
*file
,
1185 char __user
*user_buf
,
1186 size_t count
, loff_t
*ppos
)
1188 struct ieee80211_vif
*vif
= file
->private_data
;
1189 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1190 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1193 const size_t bufsz
= sizeof(buf
);
1196 mutex_lock(&mvm
->mutex
);
1197 last_abort_id
= mvm
->tof_data
.last_abort_id
;
1198 mutex_unlock(&mvm
->mutex
);
1200 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "last_abort_id = %d\n",
1202 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1205 static ssize_t
iwl_dbgfs_tof_range_response_read(struct file
*file
,
1206 char __user
*user_buf
,
1207 size_t count
, loff_t
*ppos
)
1209 struct ieee80211_vif
*vif
= file
->private_data
;
1210 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1211 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1214 const size_t bufsz
= sizeof(struct iwl_tof_range_rsp_ntfy
) + 256;
1215 struct iwl_tof_range_rsp_ntfy
*cmd
;
1218 buf
= kzalloc(bufsz
, GFP_KERNEL
);
1222 mutex_lock(&mvm
->mutex
);
1223 cmd
= &mvm
->tof_data
.range_resp
;
1225 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "request_id = %d\n",
1227 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "status = %d\n",
1228 cmd
->request_status
);
1229 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "last_in_batch = %d\n",
1230 cmd
->last_in_batch
);
1231 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "num_of_aps = %d\n",
1233 for (i
= 0; i
< cmd
->num_of_aps
; i
++) {
1234 struct iwl_tof_range_rsp_ap_entry_ntfy
*ap
= &cmd
->ap
[i
];
1236 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1237 "ap %.2d: bssid=%pM status=%hhd bw=%hhd"
1238 " rtt=%d rtt_var=%d rtt_spread=%d"
1239 " rssi=%hhd rssi_spread=%hhd"
1240 " range=%d range_var=%d"
1242 i
, ap
->bssid
, ap
->measure_status
,
1244 ap
->rtt
, ap
->rtt_variance
, ap
->rtt_spread
,
1245 ap
->rssi
, ap
->rssi_spread
, ap
->range
,
1246 ap
->range_variance
, ap
->timestamp
);
1248 mutex_unlock(&mvm
->mutex
);
1250 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1255 static ssize_t
iwl_dbgfs_low_latency_write(struct ieee80211_vif
*vif
, char *buf
,
1256 size_t count
, loff_t
*ppos
)
1258 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1259 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1264 ret
= kstrtou8(buf
, 0, &value
);
1270 mutex_lock(&mvm
->mutex
);
1271 prev
= iwl_mvm_vif_low_latency(mvmvif
);
1272 mvmvif
->low_latency_dbgfs
= value
;
1273 iwl_mvm_update_low_latency(mvm
, vif
, prev
);
1274 mutex_unlock(&mvm
->mutex
);
1279 static ssize_t
iwl_dbgfs_low_latency_read(struct file
*file
,
1280 char __user
*user_buf
,
1281 size_t count
, loff_t
*ppos
)
1283 struct ieee80211_vif
*vif
= file
->private_data
;
1284 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1288 len
= snprintf(buf
, sizeof(buf
) - 1,
1289 "traffic=%d\ndbgfs=%d\nvcmd=%d\n",
1290 mvmvif
->low_latency_traffic
,
1291 mvmvif
->low_latency_dbgfs
,
1292 mvmvif
->low_latency_vcmd
);
1293 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1296 static ssize_t
iwl_dbgfs_uapsd_misbehaving_read(struct file
*file
,
1297 char __user
*user_buf
,
1298 size_t count
, loff_t
*ppos
)
1300 struct ieee80211_vif
*vif
= file
->private_data
;
1301 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1305 len
= sprintf(buf
, "%pM\n", mvmvif
->uapsd_misbehaving_bssid
);
1306 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1309 static ssize_t
iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif
*vif
,
1310 char *buf
, size_t count
,
1313 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1314 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1317 mutex_lock(&mvm
->mutex
);
1318 ret
= mac_pton(buf
, mvmvif
->uapsd_misbehaving_bssid
);
1319 mutex_unlock(&mvm
->mutex
);
1321 return ret
? count
: -EINVAL
;
1324 static ssize_t
iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif
*vif
, char *buf
,
1325 size_t count
, loff_t
*ppos
)
1327 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1328 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1329 struct ieee80211_chanctx_conf
*chanctx_conf
;
1330 struct iwl_mvm_phy_ctxt
*phy_ctxt
;
1334 ret
= kstrtou16(buf
, 0, &value
);
1338 mutex_lock(&mvm
->mutex
);
1341 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
1342 /* make sure the channel context is assigned */
1343 if (!chanctx_conf
) {
1345 mutex_unlock(&mvm
->mutex
);
1349 phy_ctxt
= &mvm
->phy_ctxts
[*(u16
*)chanctx_conf
->drv_priv
];
1352 mvm
->dbgfs_rx_phyinfo
= value
;
1354 ret
= iwl_mvm_phy_ctxt_changed(mvm
, phy_ctxt
, &chanctx_conf
->min_def
,
1355 chanctx_conf
->rx_chains_static
,
1356 chanctx_conf
->rx_chains_dynamic
);
1357 mutex_unlock(&mvm
->mutex
);
1359 return ret
?: count
;
1362 static ssize_t
iwl_dbgfs_rx_phyinfo_read(struct file
*file
,
1363 char __user
*user_buf
,
1364 size_t count
, loff_t
*ppos
)
1366 struct ieee80211_vif
*vif
= file
->private_data
;
1367 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1370 snprintf(buf
, sizeof(buf
), "0x%04x\n", mvmvif
->mvm
->dbgfs_rx_phyinfo
);
1372 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, sizeof(buf
));
1375 static void iwl_dbgfs_quota_check(void *data
, u8
*mac
,
1376 struct ieee80211_vif
*vif
)
1378 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1381 if (mvmvif
->dbgfs_quota_min
)
1385 static ssize_t
iwl_dbgfs_quota_min_write(struct ieee80211_vif
*vif
, char *buf
,
1386 size_t count
, loff_t
*ppos
)
1388 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1389 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1393 ret
= kstrtou16(buf
, 0, &value
);
1400 mutex_lock(&mvm
->mutex
);
1402 mvmvif
->dbgfs_quota_min
= 0;
1403 ieee80211_iterate_interfaces(mvm
->hw
, IEEE80211_IFACE_ITER_NORMAL
,
1404 iwl_dbgfs_quota_check
, &ret
);
1406 mvmvif
->dbgfs_quota_min
= value
;
1407 iwl_mvm_update_quotas(mvm
, false, NULL
);
1409 mutex_unlock(&mvm
->mutex
);
1411 return ret
?: count
;
1414 static ssize_t
iwl_dbgfs_quota_min_read(struct file
*file
,
1415 char __user
*user_buf
,
1416 size_t count
, loff_t
*ppos
)
1418 struct ieee80211_vif
*vif
= file
->private_data
;
1419 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1423 len
= snprintf(buf
, sizeof(buf
), "%d\n", mvmvif
->dbgfs_quota_min
);
1425 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1428 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1429 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1430 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1431 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1432 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
1433 if (!debugfs_create_file(#name, mode, parent, vif, \
1434 &iwl_dbgfs_##name##_ops)) \
1438 MVM_DEBUGFS_READ_FILE_OPS(mac_params
);
1439 MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt
);
1440 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params
, 32);
1441 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params
, 256);
1442 MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency
, 10);
1443 MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving
, 20);
1444 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo
, 10);
1445 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable
, 32);
1446 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request
, 512);
1447 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext
, 32);
1448 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort
, 32);
1449 MVM_DEBUGFS_READ_FILE_OPS(tof_range_response
);
1450 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params
, 32);
1451 MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min
, 32);
1453 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1455 struct dentry
*dbgfs_dir
= vif
->debugfs_dir
;
1456 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1460 * Check if debugfs directory already exist before creating it.
1461 * This may happen when, for example, resetting hw or suspend-resume
1463 if (!dbgfs_dir
|| mvmvif
->dbgfs_dir
)
1466 mvmvif
->dbgfs_dir
= debugfs_create_dir("iwlmvm", dbgfs_dir
);
1468 if (!mvmvif
->dbgfs_dir
) {
1469 IWL_ERR(mvm
, "Failed to create debugfs directory under %s\n",
1470 dbgfs_dir
->d_name
.name
);
1474 if (iwlmvm_mod_params
.power_scheme
!= IWL_POWER_SCHEME_CAM
&&
1475 ((vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
) ||
1476 (vif
->type
== NL80211_IFTYPE_STATION
&& vif
->p2p
&&
1477 mvm
->fw
->ucode_capa
.flags
& IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM
)))
1478 MVM_DEBUGFS_ADD_FILE_VIF(pm_params
, mvmvif
->dbgfs_dir
, S_IWUSR
|
1481 MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt
, mvmvif
->dbgfs_dir
, S_IRUSR
);
1482 MVM_DEBUGFS_ADD_FILE_VIF(mac_params
, mvmvif
->dbgfs_dir
, S_IRUSR
);
1483 MVM_DEBUGFS_ADD_FILE_VIF(low_latency
, mvmvif
->dbgfs_dir
,
1485 MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving
, mvmvif
->dbgfs_dir
,
1487 MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo
, mvmvif
->dbgfs_dir
,
1489 MVM_DEBUGFS_ADD_FILE_VIF(quota_min
, mvmvif
->dbgfs_dir
,
1492 if (vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
1493 mvmvif
== mvm
->bf_allowed_vif
)
1494 MVM_DEBUGFS_ADD_FILE_VIF(bf_params
, mvmvif
->dbgfs_dir
,
1497 if (fw_has_capa(&mvm
->fw
->ucode_capa
, IWL_UCODE_TLV_CAPA_TOF_SUPPORT
) &&
1498 !vif
->p2p
&& (vif
->type
!= NL80211_IFTYPE_P2P_DEVICE
)) {
1499 if (IWL_MVM_TOF_IS_RESPONDER
&& vif
->type
== NL80211_IFTYPE_AP
)
1500 MVM_DEBUGFS_ADD_FILE_VIF(tof_responder_params
,
1504 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_request
, mvmvif
->dbgfs_dir
,
1506 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_req_ext
, mvmvif
->dbgfs_dir
,
1508 MVM_DEBUGFS_ADD_FILE_VIF(tof_enable
, mvmvif
->dbgfs_dir
,
1510 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_abort
, mvmvif
->dbgfs_dir
,
1512 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_response
, mvmvif
->dbgfs_dir
,
1517 * Create symlink for convenience pointing to interface specific
1518 * debugfs entries for the driver. For example, under
1519 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1521 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1523 snprintf(buf
, 100, "../../../%s/%s/%s/%s",
1524 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
1525 dbgfs_dir
->d_parent
->d_name
.name
,
1526 dbgfs_dir
->d_name
.name
,
1527 mvmvif
->dbgfs_dir
->d_name
.name
);
1529 mvmvif
->dbgfs_slink
= debugfs_create_symlink(dbgfs_dir
->d_name
.name
,
1530 mvm
->debugfs_dir
, buf
);
1531 if (!mvmvif
->dbgfs_slink
)
1532 IWL_ERR(mvm
, "Can't create debugfs symbolic link under %s\n",
1533 dbgfs_dir
->d_name
.name
);
1536 IWL_ERR(mvm
, "Can't create debugfs entity\n");
1539 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1541 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1543 debugfs_remove(mvmvif
->dbgfs_slink
);
1544 mvmvif
->dbgfs_slink
= NULL
;
1546 debugfs_remove_recursive(mvmvif
->dbgfs_dir
);
1547 mvmvif
->dbgfs_dir
= NULL
;