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 iwl_mvm_sta
*mvm_sta
;
286 mvm_sta
= iwl_mvm_sta_from_staid_protected(mvm
, ap_sta_id
);
288 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
289 "ap_sta_id %d - reduced Tx power %d\n",
291 mvm_sta
->bt_reduced_txpower
);
296 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
298 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
299 "idle rx chains %d, active rx chains: %d\n",
300 chanctx_conf
->rx_chains_static
,
301 chanctx_conf
->rx_chains_dynamic
);
304 mutex_unlock(&mvm
->mutex
);
306 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
309 static void iwl_dbgfs_update_bf(struct ieee80211_vif
*vif
,
310 enum iwl_dbgfs_bf_mask param
, int value
)
312 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
313 struct iwl_dbgfs_bf
*dbgfs_bf
= &mvmvif
->dbgfs_bf
;
315 dbgfs_bf
->mask
|= param
;
318 case MVM_DEBUGFS_BF_ENERGY_DELTA
:
319 dbgfs_bf
->bf_energy_delta
= value
;
321 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
322 dbgfs_bf
->bf_roaming_energy_delta
= value
;
324 case MVM_DEBUGFS_BF_ROAMING_STATE
:
325 dbgfs_bf
->bf_roaming_state
= value
;
327 case MVM_DEBUGFS_BF_TEMP_THRESHOLD
:
328 dbgfs_bf
->bf_temp_threshold
= value
;
330 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER
:
331 dbgfs_bf
->bf_temp_fast_filter
= value
;
333 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
:
334 dbgfs_bf
->bf_temp_slow_filter
= value
;
336 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
337 dbgfs_bf
->bf_enable_beacon_filter
= value
;
339 case MVM_DEBUGFS_BF_DEBUG_FLAG
:
340 dbgfs_bf
->bf_debug_flag
= value
;
342 case MVM_DEBUGFS_BF_ESCAPE_TIMER
:
343 dbgfs_bf
->bf_escape_timer
= value
;
345 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
346 dbgfs_bf
->ba_enable_beacon_abort
= value
;
348 case MVM_DEBUGFS_BA_ESCAPE_TIMER
:
349 dbgfs_bf
->ba_escape_timer
= value
;
354 static ssize_t
iwl_dbgfs_bf_params_write(struct ieee80211_vif
*vif
, char *buf
,
355 size_t count
, loff_t
*ppos
)
357 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
358 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
359 enum iwl_dbgfs_bf_mask param
;
362 if (!strncmp("bf_energy_delta=", buf
, 16)) {
363 if (sscanf(buf
+16, "%d", &value
) != 1)
365 if (value
< IWL_BF_ENERGY_DELTA_MIN
||
366 value
> IWL_BF_ENERGY_DELTA_MAX
)
368 param
= MVM_DEBUGFS_BF_ENERGY_DELTA
;
369 } else if (!strncmp("bf_roaming_energy_delta=", buf
, 24)) {
370 if (sscanf(buf
+24, "%d", &value
) != 1)
372 if (value
< IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
373 value
> IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
375 param
= MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
376 } else if (!strncmp("bf_roaming_state=", buf
, 17)) {
377 if (sscanf(buf
+17, "%d", &value
) != 1)
379 if (value
< IWL_BF_ROAMING_STATE_MIN
||
380 value
> IWL_BF_ROAMING_STATE_MAX
)
382 param
= MVM_DEBUGFS_BF_ROAMING_STATE
;
383 } else if (!strncmp("bf_temp_threshold=", buf
, 18)) {
384 if (sscanf(buf
+18, "%d", &value
) != 1)
386 if (value
< IWL_BF_TEMP_THRESHOLD_MIN
||
387 value
> IWL_BF_TEMP_THRESHOLD_MAX
)
389 param
= MVM_DEBUGFS_BF_TEMP_THRESHOLD
;
390 } else if (!strncmp("bf_temp_fast_filter=", buf
, 20)) {
391 if (sscanf(buf
+20, "%d", &value
) != 1)
393 if (value
< IWL_BF_TEMP_FAST_FILTER_MIN
||
394 value
> IWL_BF_TEMP_FAST_FILTER_MAX
)
396 param
= MVM_DEBUGFS_BF_TEMP_FAST_FILTER
;
397 } else if (!strncmp("bf_temp_slow_filter=", buf
, 20)) {
398 if (sscanf(buf
+20, "%d", &value
) != 1)
400 if (value
< IWL_BF_TEMP_SLOW_FILTER_MIN
||
401 value
> IWL_BF_TEMP_SLOW_FILTER_MAX
)
403 param
= MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
;
404 } else if (!strncmp("bf_enable_beacon_filter=", buf
, 24)) {
405 if (sscanf(buf
+24, "%d", &value
) != 1)
407 if (value
< 0 || value
> 1)
409 param
= MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
410 } else if (!strncmp("bf_debug_flag=", buf
, 14)) {
411 if (sscanf(buf
+14, "%d", &value
) != 1)
413 if (value
< 0 || value
> 1)
415 param
= MVM_DEBUGFS_BF_DEBUG_FLAG
;
416 } else if (!strncmp("bf_escape_timer=", buf
, 16)) {
417 if (sscanf(buf
+16, "%d", &value
) != 1)
419 if (value
< IWL_BF_ESCAPE_TIMER_MIN
||
420 value
> IWL_BF_ESCAPE_TIMER_MAX
)
422 param
= MVM_DEBUGFS_BF_ESCAPE_TIMER
;
423 } else if (!strncmp("ba_escape_timer=", buf
, 16)) {
424 if (sscanf(buf
+16, "%d", &value
) != 1)
426 if (value
< IWL_BA_ESCAPE_TIMER_MIN
||
427 value
> IWL_BA_ESCAPE_TIMER_MAX
)
429 param
= MVM_DEBUGFS_BA_ESCAPE_TIMER
;
430 } else if (!strncmp("ba_enable_beacon_abort=", buf
, 23)) {
431 if (sscanf(buf
+23, "%d", &value
) != 1)
433 if (value
< 0 || value
> 1)
435 param
= MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
440 mutex_lock(&mvm
->mutex
);
441 iwl_dbgfs_update_bf(vif
, param
, value
);
442 if (param
== MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&& !value
)
443 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
, 0);
445 ret
= iwl_mvm_enable_beacon_filter(mvm
, vif
, 0);
446 mutex_unlock(&mvm
->mutex
);
451 static ssize_t
iwl_dbgfs_bf_params_read(struct file
*file
,
452 char __user
*user_buf
,
453 size_t count
, loff_t
*ppos
)
455 struct ieee80211_vif
*vif
= file
->private_data
;
456 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
459 const size_t bufsz
= sizeof(buf
);
460 struct iwl_beacon_filter_cmd cmd
= {
461 IWL_BF_CMD_CONFIG_DEFAULTS
,
462 .bf_enable_beacon_filter
=
463 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
),
464 .ba_enable_beacon_abort
=
465 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
),
468 iwl_mvm_beacon_filter_debugfs_parameters(vif
, &cmd
);
469 if (mvmvif
->bf_data
.bf_enabled
)
470 cmd
.bf_enable_beacon_filter
= cpu_to_le32(1);
472 cmd
.bf_enable_beacon_filter
= 0;
474 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_energy_delta = %d\n",
475 le32_to_cpu(cmd
.bf_energy_delta
));
476 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_energy_delta = %d\n",
477 le32_to_cpu(cmd
.bf_roaming_energy_delta
));
478 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_state = %d\n",
479 le32_to_cpu(cmd
.bf_roaming_state
));
480 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_threshold = %d\n",
481 le32_to_cpu(cmd
.bf_temp_threshold
));
482 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_fast_filter = %d\n",
483 le32_to_cpu(cmd
.bf_temp_fast_filter
));
484 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_slow_filter = %d\n",
485 le32_to_cpu(cmd
.bf_temp_slow_filter
));
486 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_enable_beacon_filter = %d\n",
487 le32_to_cpu(cmd
.bf_enable_beacon_filter
));
488 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_debug_flag = %d\n",
489 le32_to_cpu(cmd
.bf_debug_flag
));
490 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_escape_timer = %d\n",
491 le32_to_cpu(cmd
.bf_escape_timer
));
492 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_escape_timer = %d\n",
493 le32_to_cpu(cmd
.ba_escape_timer
));
494 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_enable_beacon_abort = %d\n",
495 le32_to_cpu(cmd
.ba_enable_beacon_abort
));
497 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
500 static inline char *iwl_dbgfs_is_match(char *name
, char *buf
)
502 int len
= strlen(name
);
504 return !strncmp(name
, buf
, len
) ? buf
+ len
: NULL
;
507 static ssize_t
iwl_dbgfs_tof_enable_write(struct ieee80211_vif
*vif
,
509 size_t count
, loff_t
*ppos
)
511 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
512 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
517 mutex_lock(&mvm
->mutex
);
519 data
= iwl_dbgfs_is_match("tof_disabled=", buf
);
521 ret
= kstrtou32(data
, 10, &value
);
523 mvm
->tof_data
.tof_cfg
.tof_disabled
= value
;
527 data
= iwl_dbgfs_is_match("one_sided_disabled=", buf
);
529 ret
= kstrtou32(data
, 10, &value
);
531 mvm
->tof_data
.tof_cfg
.one_sided_disabled
= value
;
535 data
= iwl_dbgfs_is_match("is_debug_mode=", buf
);
537 ret
= kstrtou32(data
, 10, &value
);
539 mvm
->tof_data
.tof_cfg
.is_debug_mode
= value
;
543 data
= iwl_dbgfs_is_match("is_buf=", buf
);
545 ret
= kstrtou32(data
, 10, &value
);
547 mvm
->tof_data
.tof_cfg
.is_buf_required
= value
;
551 data
= iwl_dbgfs_is_match("send_tof_cfg=", buf
);
553 ret
= kstrtou32(data
, 10, &value
);
554 if (ret
== 0 && value
) {
555 ret
= iwl_mvm_tof_config_cmd(mvm
);
561 mutex_unlock(&mvm
->mutex
);
566 static ssize_t
iwl_dbgfs_tof_enable_read(struct file
*file
,
567 char __user
*user_buf
,
568 size_t count
, loff_t
*ppos
)
570 struct ieee80211_vif
*vif
= file
->private_data
;
571 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
572 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
575 const size_t bufsz
= sizeof(buf
);
576 struct iwl_tof_config_cmd
*cmd
;
578 cmd
= &mvm
->tof_data
.tof_cfg
;
580 mutex_lock(&mvm
->mutex
);
582 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "tof_disabled = %d\n",
584 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "one_sided_disabled = %d\n",
585 cmd
->one_sided_disabled
);
586 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "is_debug_mode = %d\n",
588 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "is_buf_required = %d\n",
589 cmd
->is_buf_required
);
591 mutex_unlock(&mvm
->mutex
);
593 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
596 static ssize_t
iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif
*vif
,
598 size_t count
, loff_t
*ppos
)
600 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
601 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
606 mutex_lock(&mvm
->mutex
);
608 data
= iwl_dbgfs_is_match("burst_period=", buf
);
610 ret
= kstrtou32(data
, 10, &value
);
612 mvm
->tof_data
.responder_cfg
.burst_period
=
617 data
= iwl_dbgfs_is_match("min_delta_ftm=", buf
);
619 ret
= kstrtou32(data
, 10, &value
);
621 mvm
->tof_data
.responder_cfg
.min_delta_ftm
= value
;
625 data
= iwl_dbgfs_is_match("burst_duration=", buf
);
627 ret
= kstrtou32(data
, 10, &value
);
629 mvm
->tof_data
.responder_cfg
.burst_duration
= value
;
633 data
= iwl_dbgfs_is_match("num_of_burst_exp=", buf
);
635 ret
= kstrtou32(data
, 10, &value
);
637 mvm
->tof_data
.responder_cfg
.num_of_burst_exp
= value
;
641 data
= iwl_dbgfs_is_match("abort_responder=", buf
);
643 ret
= kstrtou32(data
, 10, &value
);
645 mvm
->tof_data
.responder_cfg
.abort_responder
= value
;
649 data
= iwl_dbgfs_is_match("get_ch_est=", buf
);
651 ret
= kstrtou32(data
, 10, &value
);
653 mvm
->tof_data
.responder_cfg
.get_ch_est
= value
;
657 data
= iwl_dbgfs_is_match("recv_sta_req_params=", buf
);
659 ret
= kstrtou32(data
, 10, &value
);
661 mvm
->tof_data
.responder_cfg
.recv_sta_req_params
= value
;
665 data
= iwl_dbgfs_is_match("channel_num=", buf
);
667 ret
= kstrtou32(data
, 10, &value
);
669 mvm
->tof_data
.responder_cfg
.channel_num
= value
;
673 data
= iwl_dbgfs_is_match("bandwidth=", buf
);
675 ret
= kstrtou32(data
, 10, &value
);
677 mvm
->tof_data
.responder_cfg
.bandwidth
= value
;
681 data
= iwl_dbgfs_is_match("rate=", buf
);
683 ret
= kstrtou32(data
, 10, &value
);
685 mvm
->tof_data
.responder_cfg
.rate
= value
;
689 data
= iwl_dbgfs_is_match("bssid=", buf
);
691 u8
*mac
= mvm
->tof_data
.responder_cfg
.bssid
;
693 if (!mac_pton(data
, mac
)) {
699 data
= iwl_dbgfs_is_match("tsf_timer_offset_msecs=", buf
);
701 ret
= kstrtou32(data
, 10, &value
);
703 mvm
->tof_data
.responder_cfg
.tsf_timer_offset_msecs
=
708 data
= iwl_dbgfs_is_match("toa_offset=", buf
);
710 ret
= kstrtou32(data
, 10, &value
);
712 mvm
->tof_data
.responder_cfg
.toa_offset
=
717 data
= iwl_dbgfs_is_match("center_freq=", buf
);
719 struct iwl_tof_responder_config_cmd
*cmd
=
720 &mvm
->tof_data
.responder_cfg
;
722 ret
= kstrtou32(data
, 10, &value
);
723 if (ret
== 0 && value
) {
724 enum nl80211_band band
= (cmd
->channel_num
<= 14) ?
727 struct ieee80211_channel chn
= {
729 .center_freq
= ieee80211_channel_to_frequency(
730 cmd
->channel_num
, band
),
732 struct cfg80211_chan_def chandef
= {
735 ieee80211_channel_to_frequency(value
,
739 cmd
->ctrl_ch_position
= iwl_mvm_get_ctrl_pos(&chandef
);
744 data
= iwl_dbgfs_is_match("ftm_per_burst=", buf
);
746 ret
= kstrtou32(data
, 10, &value
);
748 mvm
->tof_data
.responder_cfg
.ftm_per_burst
= value
;
752 data
= iwl_dbgfs_is_match("ftm_resp_ts_avail=", buf
);
754 ret
= kstrtou32(data
, 10, &value
);
756 mvm
->tof_data
.responder_cfg
.ftm_resp_ts_avail
= value
;
760 data
= iwl_dbgfs_is_match("asap_mode=", buf
);
762 ret
= kstrtou32(data
, 10, &value
);
764 mvm
->tof_data
.responder_cfg
.asap_mode
= value
;
768 data
= iwl_dbgfs_is_match("send_responder_cfg=", buf
);
770 ret
= kstrtou32(data
, 10, &value
);
771 if (ret
== 0 && value
) {
772 ret
= iwl_mvm_tof_responder_cmd(mvm
, vif
);
778 mutex_unlock(&mvm
->mutex
);
783 static ssize_t
iwl_dbgfs_tof_responder_params_read(struct file
*file
,
784 char __user
*user_buf
,
785 size_t count
, loff_t
*ppos
)
787 struct ieee80211_vif
*vif
= file
->private_data
;
788 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
789 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
792 const size_t bufsz
= sizeof(buf
);
793 struct iwl_tof_responder_config_cmd
*cmd
;
795 cmd
= &mvm
->tof_data
.responder_cfg
;
797 mutex_lock(&mvm
->mutex
);
799 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "burst_period = %d\n",
800 le16_to_cpu(cmd
->burst_period
));
801 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "burst_duration = %d\n",
802 cmd
->burst_duration
);
803 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "bandwidth = %d\n",
805 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "channel_num = %d\n",
807 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "ctrl_ch_position = 0x%x\n",
808 cmd
->ctrl_ch_position
);
809 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "bssid = %pM\n",
811 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "min_delta_ftm = %d\n",
813 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "num_of_burst_exp = %d\n",
814 cmd
->num_of_burst_exp
);
815 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "rate = %d\n", cmd
->rate
);
816 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "abort_responder = %d\n",
817 cmd
->abort_responder
);
818 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "get_ch_est = %d\n",
820 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "recv_sta_req_params = %d\n",
821 cmd
->recv_sta_req_params
);
822 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "ftm_per_burst = %d\n",
824 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "ftm_resp_ts_avail = %d\n",
825 cmd
->ftm_resp_ts_avail
);
826 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "asap_mode = %d\n",
828 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
829 "tsf_timer_offset_msecs = %d\n",
830 le16_to_cpu(cmd
->tsf_timer_offset_msecs
));
831 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "toa_offset = %d\n",
832 le16_to_cpu(cmd
->toa_offset
));
834 mutex_unlock(&mvm
->mutex
);
836 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
839 static ssize_t
iwl_dbgfs_tof_range_request_write(struct ieee80211_vif
*vif
,
840 char *buf
, size_t count
,
843 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
844 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
849 mutex_lock(&mvm
->mutex
);
851 data
= iwl_dbgfs_is_match("request_id=", buf
);
853 ret
= kstrtou32(data
, 10, &value
);
855 mvm
->tof_data
.range_req
.request_id
= value
;
859 data
= iwl_dbgfs_is_match("initiator=", buf
);
861 ret
= kstrtou32(data
, 10, &value
);
863 mvm
->tof_data
.range_req
.initiator
= value
;
867 data
= iwl_dbgfs_is_match("one_sided_los_disable=", buf
);
869 ret
= kstrtou32(data
, 10, &value
);
871 mvm
->tof_data
.range_req
.one_sided_los_disable
= value
;
875 data
= iwl_dbgfs_is_match("req_timeout=", buf
);
877 ret
= kstrtou32(data
, 10, &value
);
879 mvm
->tof_data
.range_req
.req_timeout
= value
;
883 data
= iwl_dbgfs_is_match("report_policy=", buf
);
885 ret
= kstrtou32(data
, 10, &value
);
887 mvm
->tof_data
.range_req
.report_policy
= value
;
891 data
= iwl_dbgfs_is_match("macaddr_random=", buf
);
893 ret
= kstrtou32(data
, 10, &value
);
895 mvm
->tof_data
.range_req
.macaddr_random
= value
;
899 data
= iwl_dbgfs_is_match("num_of_ap=", buf
);
901 ret
= kstrtou32(data
, 10, &value
);
903 mvm
->tof_data
.range_req
.num_of_ap
= value
;
907 data
= iwl_dbgfs_is_match("macaddr_template=", buf
);
911 if (!mac_pton(data
, mac
)) {
915 memcpy(mvm
->tof_data
.range_req
.macaddr_template
, mac
, ETH_ALEN
);
919 data
= iwl_dbgfs_is_match("macaddr_mask=", buf
);
923 if (!mac_pton(data
, mac
)) {
927 memcpy(mvm
->tof_data
.range_req
.macaddr_mask
, mac
, ETH_ALEN
);
931 data
= iwl_dbgfs_is_match("ap=", buf
);
933 struct iwl_tof_range_req_ap_entry ap
= {};
934 int size
= sizeof(struct iwl_tof_range_req_ap_entry
);
939 if (sscanf(data
, "%u %hhd %hhd %hhd"
940 "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
943 "%hhx %hhd %hhd %hhd",
944 &i
, &ap
.channel_num
, &ap
.bandwidth
,
945 &ap
.ctrl_ch_position
,
946 mac
, mac
+ 1, mac
+ 2, mac
+ 3, mac
+ 4, mac
+ 5,
947 &ap
.measure_type
, &ap
.num_of_bursts
,
949 &ap
.samples_per_burst
, &ap
.retries_per_sample
,
950 &ap
.tsf_delta
, &ap
.location_req
, &ap
.asap_mode
,
951 &ap
.enable_dyn_ack
, &ap
.rssi
) != 20) {
955 if (i
>= IWL_MVM_TOF_MAX_APS
) {
956 IWL_ERR(mvm
, "Invalid AP index %d\n", i
);
961 ap
.burst_period
= cpu_to_le16(burst_period
);
963 memcpy(&mvm
->tof_data
.range_req
.ap
[i
], &ap
, size
);
967 data
= iwl_dbgfs_is_match("send_range_request=", buf
);
969 ret
= kstrtou32(data
, 10, &value
);
970 if (ret
== 0 && value
)
971 ret
= iwl_mvm_tof_range_request_cmd(mvm
, vif
);
977 mutex_unlock(&mvm
->mutex
);
981 static ssize_t
iwl_dbgfs_tof_range_request_read(struct file
*file
,
982 char __user
*user_buf
,
983 size_t count
, loff_t
*ppos
)
985 struct ieee80211_vif
*vif
= file
->private_data
;
986 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
987 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
990 const size_t bufsz
= sizeof(buf
);
991 struct iwl_tof_range_req_cmd
*cmd
;
994 cmd
= &mvm
->tof_data
.range_req
;
996 mutex_lock(&mvm
->mutex
);
998 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "request_id= %d\n",
1000 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "initiator= %d\n",
1002 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "one_sided_los_disable = %d\n",
1003 cmd
->one_sided_los_disable
);
1004 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "req_timeout= %d\n",
1006 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "report_policy= %d\n",
1007 cmd
->report_policy
);
1008 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "macaddr_random= %d\n",
1009 cmd
->macaddr_random
);
1010 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "macaddr_template= %pM\n",
1011 cmd
->macaddr_template
);
1012 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "macaddr_mask= %pM\n",
1014 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "num_of_ap= %d\n",
1016 for (i
= 0; i
< cmd
->num_of_ap
; i
++) {
1017 struct iwl_tof_range_req_ap_entry
*ap
= &cmd
->ap
[i
];
1019 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1020 "ap %.2d: channel_num=%hhd bw=%hhd"
1021 " control=%hhd bssid=%pM type=%hhd"
1022 " num_of_bursts=%hhd burst_period=%hd ftm=%hhd"
1023 " retries=%hhd tsf_delta=%d"
1024 " tsf_delta_direction=%hhd location_req=0x%hhx "
1025 " asap=%hhd enable=%hhd rssi=%hhd\n",
1026 i
, ap
->channel_num
, ap
->bandwidth
,
1027 ap
->ctrl_ch_position
, ap
->bssid
,
1028 ap
->measure_type
, ap
->num_of_bursts
,
1029 ap
->burst_period
, ap
->samples_per_burst
,
1030 ap
->retries_per_sample
, ap
->tsf_delta
,
1031 ap
->tsf_delta_direction
,
1032 ap
->location_req
, ap
->asap_mode
,
1033 ap
->enable_dyn_ack
, ap
->rssi
);
1036 mutex_unlock(&mvm
->mutex
);
1038 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1041 static ssize_t
iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif
*vif
,
1043 size_t count
, loff_t
*ppos
)
1045 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1046 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1051 mutex_lock(&mvm
->mutex
);
1053 data
= iwl_dbgfs_is_match("tsf_timer_offset_msec=", buf
);
1055 ret
= kstrtou32(data
, 10, &value
);
1057 mvm
->tof_data
.range_req_ext
.tsf_timer_offset_msec
=
1062 data
= iwl_dbgfs_is_match("min_delta_ftm=", buf
);
1064 ret
= kstrtou32(data
, 10, &value
);
1066 mvm
->tof_data
.range_req_ext
.min_delta_ftm
= value
;
1070 data
= iwl_dbgfs_is_match("ftm_format_and_bw20M=", buf
);
1072 ret
= kstrtou32(data
, 10, &value
);
1074 mvm
->tof_data
.range_req_ext
.ftm_format_and_bw20M
=
1079 data
= iwl_dbgfs_is_match("ftm_format_and_bw40M=", buf
);
1081 ret
= kstrtou32(data
, 10, &value
);
1083 mvm
->tof_data
.range_req_ext
.ftm_format_and_bw40M
=
1088 data
= iwl_dbgfs_is_match("ftm_format_and_bw80M=", buf
);
1090 ret
= kstrtou32(data
, 10, &value
);
1092 mvm
->tof_data
.range_req_ext
.ftm_format_and_bw80M
=
1097 data
= iwl_dbgfs_is_match("send_range_req_ext=", buf
);
1099 ret
= kstrtou32(data
, 10, &value
);
1100 if (ret
== 0 && value
)
1101 ret
= iwl_mvm_tof_range_request_ext_cmd(mvm
, vif
);
1107 mutex_unlock(&mvm
->mutex
);
1108 return ret
?: count
;
1111 static ssize_t
iwl_dbgfs_tof_range_req_ext_read(struct file
*file
,
1112 char __user
*user_buf
,
1113 size_t count
, loff_t
*ppos
)
1115 struct ieee80211_vif
*vif
= file
->private_data
;
1116 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1117 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1120 const size_t bufsz
= sizeof(buf
);
1121 struct iwl_tof_range_req_ext_cmd
*cmd
;
1123 cmd
= &mvm
->tof_data
.range_req_ext
;
1125 mutex_lock(&mvm
->mutex
);
1127 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1128 "tsf_timer_offset_msec = %hd\n",
1129 cmd
->tsf_timer_offset_msec
);
1130 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "min_delta_ftm = %hhd\n",
1131 cmd
->min_delta_ftm
);
1132 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1133 "ftm_format_and_bw20M = %hhd\n",
1134 cmd
->ftm_format_and_bw20M
);
1135 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1136 "ftm_format_and_bw40M = %hhd\n",
1137 cmd
->ftm_format_and_bw40M
);
1138 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1139 "ftm_format_and_bw80M = %hhd\n",
1140 cmd
->ftm_format_and_bw80M
);
1142 mutex_unlock(&mvm
->mutex
);
1143 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1146 static ssize_t
iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif
*vif
,
1148 size_t count
, loff_t
*ppos
)
1150 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1151 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1153 int abort_id
, ret
= 0;
1156 mutex_lock(&mvm
->mutex
);
1158 data
= iwl_dbgfs_is_match("abort_id=", buf
);
1160 ret
= kstrtou32(data
, 10, &value
);
1162 mvm
->tof_data
.last_abort_id
= value
;
1166 data
= iwl_dbgfs_is_match("send_range_abort=", buf
);
1168 ret
= kstrtou32(data
, 10, &value
);
1169 if (ret
== 0 && value
) {
1170 abort_id
= mvm
->tof_data
.last_abort_id
;
1171 ret
= iwl_mvm_tof_range_abort_cmd(mvm
, abort_id
);
1177 mutex_unlock(&mvm
->mutex
);
1178 return ret
?: count
;
1181 static ssize_t
iwl_dbgfs_tof_range_abort_read(struct file
*file
,
1182 char __user
*user_buf
,
1183 size_t count
, loff_t
*ppos
)
1185 struct ieee80211_vif
*vif
= file
->private_data
;
1186 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1187 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1190 const size_t bufsz
= sizeof(buf
);
1193 mutex_lock(&mvm
->mutex
);
1194 last_abort_id
= mvm
->tof_data
.last_abort_id
;
1195 mutex_unlock(&mvm
->mutex
);
1197 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "last_abort_id = %d\n",
1199 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1202 static ssize_t
iwl_dbgfs_tof_range_response_read(struct file
*file
,
1203 char __user
*user_buf
,
1204 size_t count
, loff_t
*ppos
)
1206 struct ieee80211_vif
*vif
= file
->private_data
;
1207 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1208 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1211 const size_t bufsz
= sizeof(struct iwl_tof_range_rsp_ntfy
) + 256;
1212 struct iwl_tof_range_rsp_ntfy
*cmd
;
1215 buf
= kzalloc(bufsz
, GFP_KERNEL
);
1219 mutex_lock(&mvm
->mutex
);
1220 cmd
= &mvm
->tof_data
.range_resp
;
1222 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "request_id = %d\n",
1224 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "status = %d\n",
1225 cmd
->request_status
);
1226 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "last_in_batch = %d\n",
1227 cmd
->last_in_batch
);
1228 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "num_of_aps = %d\n",
1230 for (i
= 0; i
< cmd
->num_of_aps
; i
++) {
1231 struct iwl_tof_range_rsp_ap_entry_ntfy
*ap
= &cmd
->ap
[i
];
1233 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1234 "ap %.2d: bssid=%pM status=%hhd bw=%hhd"
1235 " rtt=%d rtt_var=%d rtt_spread=%d"
1236 " rssi=%hhd rssi_spread=%hhd"
1237 " range=%d range_var=%d"
1239 i
, ap
->bssid
, ap
->measure_status
,
1241 ap
->rtt
, ap
->rtt_variance
, ap
->rtt_spread
,
1242 ap
->rssi
, ap
->rssi_spread
, ap
->range
,
1243 ap
->range_variance
, ap
->timestamp
);
1245 mutex_unlock(&mvm
->mutex
);
1247 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1252 static ssize_t
iwl_dbgfs_low_latency_write(struct ieee80211_vif
*vif
, char *buf
,
1253 size_t count
, loff_t
*ppos
)
1255 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1256 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1261 ret
= kstrtou8(buf
, 0, &value
);
1267 mutex_lock(&mvm
->mutex
);
1268 prev
= iwl_mvm_vif_low_latency(mvmvif
);
1269 mvmvif
->low_latency_dbgfs
= value
;
1270 iwl_mvm_update_low_latency(mvm
, vif
, prev
);
1271 mutex_unlock(&mvm
->mutex
);
1276 static ssize_t
iwl_dbgfs_low_latency_read(struct file
*file
,
1277 char __user
*user_buf
,
1278 size_t count
, loff_t
*ppos
)
1280 struct ieee80211_vif
*vif
= file
->private_data
;
1281 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1285 len
= snprintf(buf
, sizeof(buf
) - 1,
1286 "traffic=%d\ndbgfs=%d\nvcmd=%d\n",
1287 mvmvif
->low_latency_traffic
,
1288 mvmvif
->low_latency_dbgfs
,
1289 mvmvif
->low_latency_vcmd
);
1290 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1293 static ssize_t
iwl_dbgfs_uapsd_misbehaving_read(struct file
*file
,
1294 char __user
*user_buf
,
1295 size_t count
, loff_t
*ppos
)
1297 struct ieee80211_vif
*vif
= file
->private_data
;
1298 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1302 len
= sprintf(buf
, "%pM\n", mvmvif
->uapsd_misbehaving_bssid
);
1303 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1306 static ssize_t
iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif
*vif
,
1307 char *buf
, size_t count
,
1310 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1311 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1314 mutex_lock(&mvm
->mutex
);
1315 ret
= mac_pton(buf
, mvmvif
->uapsd_misbehaving_bssid
);
1316 mutex_unlock(&mvm
->mutex
);
1318 return ret
? count
: -EINVAL
;
1321 static ssize_t
iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif
*vif
, char *buf
,
1322 size_t count
, loff_t
*ppos
)
1324 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1325 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1326 struct ieee80211_chanctx_conf
*chanctx_conf
;
1327 struct iwl_mvm_phy_ctxt
*phy_ctxt
;
1331 ret
= kstrtou16(buf
, 0, &value
);
1335 mutex_lock(&mvm
->mutex
);
1338 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
1339 /* make sure the channel context is assigned */
1340 if (!chanctx_conf
) {
1342 mutex_unlock(&mvm
->mutex
);
1346 phy_ctxt
= &mvm
->phy_ctxts
[*(u16
*)chanctx_conf
->drv_priv
];
1349 mvm
->dbgfs_rx_phyinfo
= value
;
1351 ret
= iwl_mvm_phy_ctxt_changed(mvm
, phy_ctxt
, &chanctx_conf
->min_def
,
1352 chanctx_conf
->rx_chains_static
,
1353 chanctx_conf
->rx_chains_dynamic
);
1354 mutex_unlock(&mvm
->mutex
);
1356 return ret
?: count
;
1359 static ssize_t
iwl_dbgfs_rx_phyinfo_read(struct file
*file
,
1360 char __user
*user_buf
,
1361 size_t count
, loff_t
*ppos
)
1363 struct ieee80211_vif
*vif
= file
->private_data
;
1364 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1367 snprintf(buf
, sizeof(buf
), "0x%04x\n", mvmvif
->mvm
->dbgfs_rx_phyinfo
);
1369 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, sizeof(buf
));
1372 static void iwl_dbgfs_quota_check(void *data
, u8
*mac
,
1373 struct ieee80211_vif
*vif
)
1375 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1378 if (mvmvif
->dbgfs_quota_min
)
1382 static ssize_t
iwl_dbgfs_quota_min_write(struct ieee80211_vif
*vif
, char *buf
,
1383 size_t count
, loff_t
*ppos
)
1385 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1386 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1390 ret
= kstrtou16(buf
, 0, &value
);
1397 mutex_lock(&mvm
->mutex
);
1399 mvmvif
->dbgfs_quota_min
= 0;
1400 ieee80211_iterate_interfaces(mvm
->hw
, IEEE80211_IFACE_ITER_NORMAL
,
1401 iwl_dbgfs_quota_check
, &ret
);
1403 mvmvif
->dbgfs_quota_min
= value
;
1404 iwl_mvm_update_quotas(mvm
, false, NULL
);
1406 mutex_unlock(&mvm
->mutex
);
1408 return ret
?: count
;
1411 static ssize_t
iwl_dbgfs_quota_min_read(struct file
*file
,
1412 char __user
*user_buf
,
1413 size_t count
, loff_t
*ppos
)
1415 struct ieee80211_vif
*vif
= file
->private_data
;
1416 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1420 len
= snprintf(buf
, sizeof(buf
), "%d\n", mvmvif
->dbgfs_quota_min
);
1422 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1425 static const char * const chanwidths
[] = {
1426 [NL80211_CHAN_WIDTH_20_NOHT
] = "noht",
1427 [NL80211_CHAN_WIDTH_20
] = "ht20",
1428 [NL80211_CHAN_WIDTH_40
] = "ht40",
1429 [NL80211_CHAN_WIDTH_80
] = "vht80",
1430 [NL80211_CHAN_WIDTH_80P80
] = "vht80p80",
1431 [NL80211_CHAN_WIDTH_160
] = "vht160",
1434 static bool iwl_mvm_lqm_notif_wait(struct iwl_notif_wait_data
*notif_wait
,
1435 struct iwl_rx_packet
*pkt
, void *data
)
1437 struct ieee80211_vif
*vif
= data
;
1438 struct iwl_mvm
*mvm
=
1439 container_of(notif_wait
, struct iwl_mvm
, notif_wait
);
1440 struct iwl_link_qual_msrmnt_notif
*report
= (void *)pkt
->data
;
1441 u32 num_of_stations
= le32_to_cpu(report
->number_of_stations
);
1444 IWL_INFO(mvm
, "LQM report:\n");
1445 IWL_INFO(mvm
, "\tstatus: %d\n", report
->status
);
1446 IWL_INFO(mvm
, "\tmacID: %d\n", le32_to_cpu(report
->mac_id
));
1447 IWL_INFO(mvm
, "\ttx_frame_dropped: %d\n",
1448 le32_to_cpu(report
->tx_frame_dropped
));
1449 IWL_INFO(mvm
, "\ttime_in_measurement_window: %d us\n",
1450 le32_to_cpu(report
->time_in_measurement_window
));
1451 IWL_INFO(mvm
, "\ttotal_air_time_other_stations: %d\n",
1452 le32_to_cpu(report
->total_air_time_other_stations
));
1453 IWL_INFO(mvm
, "\tchannel_freq: %d\n",
1454 vif
->bss_conf
.chandef
.center_freq1
);
1455 IWL_INFO(mvm
, "\tchannel_width: %s\n",
1456 chanwidths
[vif
->bss_conf
.chandef
.width
]);
1457 IWL_INFO(mvm
, "\tnumber_of_stations: %d\n", num_of_stations
);
1458 for (i
= 0; i
< num_of_stations
; i
++)
1459 IWL_INFO(mvm
, "\t\tsta[%d]: %d\n", i
,
1460 report
->frequent_stations_air_time
[i
]);
1465 static ssize_t
iwl_dbgfs_lqm_send_cmd_write(struct ieee80211_vif
*vif
,
1466 char *buf
, size_t count
,
1469 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1470 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
1471 struct iwl_notification_wait wait_lqm_notif
;
1472 static u16 lqm_notif
[] = {
1473 WIDE_ID(MAC_CONF_GROUP
,
1474 LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF
)
1480 if (sscanf(buf
, "%d,%d", &duration
, &timeout
) != 2)
1483 iwl_init_notification_wait(&mvm
->notif_wait
, &wait_lqm_notif
,
1484 lqm_notif
, ARRAY_SIZE(lqm_notif
),
1485 iwl_mvm_lqm_notif_wait
, vif
);
1486 mutex_lock(&mvm
->mutex
);
1487 err
= iwl_mvm_send_lqm_cmd(vif
, LQM_CMD_OPERATION_START_MEASUREMENT
,
1489 mutex_unlock(&mvm
->mutex
);
1492 IWL_ERR(mvm
, "Failed to send lqm cmdf(err=%d)\n", err
);
1493 iwl_remove_notification(&mvm
->notif_wait
, &wait_lqm_notif
);
1497 /* wait for 2 * timeout (safety guard) and convert to jiffies*/
1498 timeout
= msecs_to_jiffies((timeout
* 2) / 1000);
1500 err
= iwl_wait_notification(&mvm
->notif_wait
, &wait_lqm_notif
,
1503 IWL_ERR(mvm
, "Getting lqm notif timed out\n");
1508 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1509 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1510 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1511 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
1512 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
1513 if (!debugfs_create_file(#name, mode, parent, vif, \
1514 &iwl_dbgfs_##name##_ops)) \
1518 MVM_DEBUGFS_READ_FILE_OPS(mac_params
);
1519 MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt
);
1520 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params
, 32);
1521 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params
, 256);
1522 MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency
, 10);
1523 MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving
, 20);
1524 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo
, 10);
1525 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable
, 32);
1526 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request
, 512);
1527 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext
, 32);
1528 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort
, 32);
1529 MVM_DEBUGFS_READ_FILE_OPS(tof_range_response
);
1530 MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params
, 32);
1531 MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min
, 32);
1532 MVM_DEBUGFS_WRITE_FILE_OPS(lqm_send_cmd
, 64);
1534 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1536 struct dentry
*dbgfs_dir
= vif
->debugfs_dir
;
1537 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1541 * Check if debugfs directory already exist before creating it.
1542 * This may happen when, for example, resetting hw or suspend-resume
1544 if (!dbgfs_dir
|| mvmvif
->dbgfs_dir
)
1547 mvmvif
->dbgfs_dir
= debugfs_create_dir("iwlmvm", dbgfs_dir
);
1549 if (!mvmvif
->dbgfs_dir
) {
1550 IWL_ERR(mvm
, "Failed to create debugfs directory under %s\n",
1551 dbgfs_dir
->d_name
.name
);
1555 if (iwlmvm_mod_params
.power_scheme
!= IWL_POWER_SCHEME_CAM
&&
1556 ((vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
) ||
1557 (vif
->type
== NL80211_IFTYPE_STATION
&& vif
->p2p
&&
1558 mvm
->fw
->ucode_capa
.flags
& IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM
)))
1559 MVM_DEBUGFS_ADD_FILE_VIF(pm_params
, mvmvif
->dbgfs_dir
, S_IWUSR
|
1562 MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt
, mvmvif
->dbgfs_dir
, S_IRUSR
);
1563 MVM_DEBUGFS_ADD_FILE_VIF(mac_params
, mvmvif
->dbgfs_dir
, S_IRUSR
);
1564 MVM_DEBUGFS_ADD_FILE_VIF(low_latency
, mvmvif
->dbgfs_dir
,
1566 MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving
, mvmvif
->dbgfs_dir
,
1568 MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo
, mvmvif
->dbgfs_dir
,
1570 MVM_DEBUGFS_ADD_FILE_VIF(quota_min
, mvmvif
->dbgfs_dir
,
1572 MVM_DEBUGFS_ADD_FILE_VIF(lqm_send_cmd
, mvmvif
->dbgfs_dir
, S_IWUSR
);
1574 if (vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
1575 mvmvif
== mvm
->bf_allowed_vif
)
1576 MVM_DEBUGFS_ADD_FILE_VIF(bf_params
, mvmvif
->dbgfs_dir
,
1579 if (fw_has_capa(&mvm
->fw
->ucode_capa
, IWL_UCODE_TLV_CAPA_TOF_SUPPORT
) &&
1580 !vif
->p2p
&& (vif
->type
!= NL80211_IFTYPE_P2P_DEVICE
)) {
1581 if (IWL_MVM_TOF_IS_RESPONDER
&& vif
->type
== NL80211_IFTYPE_AP
)
1582 MVM_DEBUGFS_ADD_FILE_VIF(tof_responder_params
,
1586 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_request
, mvmvif
->dbgfs_dir
,
1588 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_req_ext
, mvmvif
->dbgfs_dir
,
1590 MVM_DEBUGFS_ADD_FILE_VIF(tof_enable
, mvmvif
->dbgfs_dir
,
1592 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_abort
, mvmvif
->dbgfs_dir
,
1594 MVM_DEBUGFS_ADD_FILE_VIF(tof_range_response
, mvmvif
->dbgfs_dir
,
1599 * Create symlink for convenience pointing to interface specific
1600 * debugfs entries for the driver. For example, under
1601 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1603 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1605 snprintf(buf
, 100, "../../../%s/%s/%s/%s",
1606 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
1607 dbgfs_dir
->d_parent
->d_name
.name
,
1608 dbgfs_dir
->d_name
.name
,
1609 mvmvif
->dbgfs_dir
->d_name
.name
);
1611 mvmvif
->dbgfs_slink
= debugfs_create_symlink(dbgfs_dir
->d_name
.name
,
1612 mvm
->debugfs_dir
, buf
);
1613 if (!mvmvif
->dbgfs_slink
)
1614 IWL_ERR(mvm
, "Can't create debugfs symbolic link under %s\n",
1615 dbgfs_dir
->d_name
.name
);
1618 IWL_ERR(mvm
, "Can't create debugfs entity\n");
1621 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1623 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1625 debugfs_remove(mvmvif
->dbgfs_slink
);
1626 mvmvif
->dbgfs_slink
= NULL
;
1628 debugfs_remove_recursive(mvmvif
->dbgfs_dir
);
1629 mvmvif
->dbgfs_dir
= NULL
;