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 - 2017 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 * The full GNU General Public License is included in this distribution
22 * in the file called COPYING.
24 * Contact Information:
25 * Intel Linux Wireless <linuxwifi@intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
31 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
32 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
33 * All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
39 * * Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * * Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in
43 * the documentation and/or other materials provided with the
45 * * Neither the name Intel Corporation nor the names of its
46 * contributors may be used to endorse or promote products derived
47 * from this software without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
52 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
53 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *****************************************************************************/
65 static void iwl_dbgfs_update_pm(struct iwl_mvm
*mvm
,
66 struct ieee80211_vif
*vif
,
67 enum iwl_dbgfs_pm_mask param
, int val
)
69 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
70 struct iwl_dbgfs_pm
*dbgfs_pm
= &mvmvif
->dbgfs_pm
;
72 dbgfs_pm
->mask
|= param
;
75 case MVM_DEBUGFS_PM_KEEP_ALIVE
: {
76 int dtimper
= vif
->bss_conf
.dtim_period
?: 1;
77 int dtimper_msec
= dtimper
* vif
->bss_conf
.beacon_int
;
79 IWL_DEBUG_POWER(mvm
, "debugfs: set keep_alive= %d sec\n", val
);
80 if (val
* MSEC_PER_SEC
< 3 * dtimper_msec
)
82 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
83 val
* MSEC_PER_SEC
, 3 * dtimper_msec
);
84 dbgfs_pm
->keep_alive_seconds
= val
;
87 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM
:
88 IWL_DEBUG_POWER(mvm
, "skip_over_dtim %s\n",
89 val
? "enabled" : "disabled");
90 dbgfs_pm
->skip_over_dtim
= val
;
92 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
:
93 IWL_DEBUG_POWER(mvm
, "skip_dtim_periods=%d\n", val
);
94 dbgfs_pm
->skip_dtim_periods
= val
;
96 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
:
97 IWL_DEBUG_POWER(mvm
, "rx_data_timeout=%d\n", val
);
98 dbgfs_pm
->rx_data_timeout
= val
;
100 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
:
101 IWL_DEBUG_POWER(mvm
, "tx_data_timeout=%d\n", val
);
102 dbgfs_pm
->tx_data_timeout
= val
;
104 case MVM_DEBUGFS_PM_LPRX_ENA
:
105 IWL_DEBUG_POWER(mvm
, "lprx %s\n", val
? "enabled" : "disabled");
106 dbgfs_pm
->lprx_ena
= val
;
108 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
:
109 IWL_DEBUG_POWER(mvm
, "lprx_rssi_threshold=%d\n", val
);
110 dbgfs_pm
->lprx_rssi_threshold
= val
;
112 case MVM_DEBUGFS_PM_SNOOZE_ENABLE
:
113 IWL_DEBUG_POWER(mvm
, "snooze_enable=%d\n", val
);
114 dbgfs_pm
->snooze_ena
= val
;
116 case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
:
117 IWL_DEBUG_POWER(mvm
, "uapsd_misbehaving_enable=%d\n", val
);
118 dbgfs_pm
->uapsd_misbehaving
= val
;
120 case MVM_DEBUGFS_PM_USE_PS_POLL
:
121 IWL_DEBUG_POWER(mvm
, "use_ps_poll=%d\n", val
);
122 dbgfs_pm
->use_ps_poll
= val
;
127 static ssize_t
iwl_dbgfs_pm_params_write(struct ieee80211_vif
*vif
, char *buf
,
128 size_t count
, loff_t
*ppos
)
130 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
131 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
132 enum iwl_dbgfs_pm_mask param
;
135 if (!strncmp("keep_alive=", buf
, 11)) {
136 if (sscanf(buf
+ 11, "%d", &val
) != 1)
138 param
= MVM_DEBUGFS_PM_KEEP_ALIVE
;
139 } else if (!strncmp("skip_over_dtim=", buf
, 15)) {
140 if (sscanf(buf
+ 15, "%d", &val
) != 1)
142 param
= MVM_DEBUGFS_PM_SKIP_OVER_DTIM
;
143 } else if (!strncmp("skip_dtim_periods=", buf
, 18)) {
144 if (sscanf(buf
+ 18, "%d", &val
) != 1)
146 param
= MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
;
147 } else if (!strncmp("rx_data_timeout=", buf
, 16)) {
148 if (sscanf(buf
+ 16, "%d", &val
) != 1)
150 param
= MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
;
151 } else if (!strncmp("tx_data_timeout=", buf
, 16)) {
152 if (sscanf(buf
+ 16, "%d", &val
) != 1)
154 param
= MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
;
155 } else if (!strncmp("lprx=", buf
, 5)) {
156 if (sscanf(buf
+ 5, "%d", &val
) != 1)
158 param
= MVM_DEBUGFS_PM_LPRX_ENA
;
159 } else if (!strncmp("lprx_rssi_threshold=", buf
, 20)) {
160 if (sscanf(buf
+ 20, "%d", &val
) != 1)
162 if (val
> POWER_LPRX_RSSI_THRESHOLD_MAX
|| val
<
163 POWER_LPRX_RSSI_THRESHOLD_MIN
)
165 param
= MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
;
166 } else if (!strncmp("snooze_enable=", buf
, 14)) {
167 if (sscanf(buf
+ 14, "%d", &val
) != 1)
169 param
= MVM_DEBUGFS_PM_SNOOZE_ENABLE
;
170 } else if (!strncmp("uapsd_misbehaving=", buf
, 18)) {
171 if (sscanf(buf
+ 18, "%d", &val
) != 1)
173 param
= MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
;
174 } else if (!strncmp("use_ps_poll=", buf
, 12)) {
175 if (sscanf(buf
+ 12, "%d", &val
) != 1)
177 param
= MVM_DEBUGFS_PM_USE_PS_POLL
;
182 mutex_lock(&mvm
->mutex
);
183 iwl_dbgfs_update_pm(mvm
, vif
, param
, val
);
184 ret
= iwl_mvm_power_update_mac(mvm
);
185 mutex_unlock(&mvm
->mutex
);
190 static ssize_t
iwl_dbgfs_tx_pwr_lmt_read(struct file
*file
,
191 char __user
*user_buf
,
192 size_t count
, loff_t
*ppos
)
194 struct ieee80211_vif
*vif
= file
->private_data
;
196 int bufsz
= sizeof(buf
);
199 pos
= scnprintf(buf
, bufsz
, "bss limit = %d\n",
200 vif
->bss_conf
.txpower
);
202 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
205 static ssize_t
iwl_dbgfs_pm_params_read(struct file
*file
,
206 char __user
*user_buf
,
207 size_t count
, loff_t
*ppos
)
209 struct ieee80211_vif
*vif
= file
->private_data
;
210 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
211 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
213 int bufsz
= sizeof(buf
);
216 pos
= iwl_mvm_power_mac_dbgfs_read(mvm
, vif
, buf
, bufsz
);
218 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
221 static ssize_t
iwl_dbgfs_mac_params_read(struct file
*file
,
222 char __user
*user_buf
,
223 size_t count
, loff_t
*ppos
)
225 struct ieee80211_vif
*vif
= file
->private_data
;
226 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
227 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
229 struct ieee80211_chanctx_conf
*chanctx_conf
;
231 int bufsz
= sizeof(buf
);
235 mutex_lock(&mvm
->mutex
);
237 ap_sta_id
= mvmvif
->ap_sta_id
;
239 switch (ieee80211_vif_type_p2p(vif
)) {
240 case NL80211_IFTYPE_ADHOC
:
241 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: ibss\n");
243 case NL80211_IFTYPE_STATION
:
244 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: bss\n");
246 case NL80211_IFTYPE_AP
:
247 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: ap\n");
249 case NL80211_IFTYPE_P2P_CLIENT
:
250 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p client\n");
252 case NL80211_IFTYPE_P2P_GO
:
253 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p go\n");
255 case NL80211_IFTYPE_P2P_DEVICE
:
256 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p dev\n");
262 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "mac id/color: %d / %d\n",
263 mvmvif
->id
, mvmvif
->color
);
264 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bssid: %pM\n",
265 vif
->bss_conf
.bssid
);
266 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "Load: %d\n",
267 mvm
->tcm
.result
.load
[mvmvif
->id
]);
268 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "QoS:\n");
269 for (i
= 0; i
< ARRAY_SIZE(mvmvif
->queue_params
); i
++)
270 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
271 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
272 i
, mvmvif
->queue_params
[i
].txop
,
273 mvmvif
->queue_params
[i
].cw_min
,
274 mvmvif
->queue_params
[i
].cw_max
,
275 mvmvif
->queue_params
[i
].aifs
,
276 mvmvif
->queue_params
[i
].uapsd
);
278 if (vif
->type
== NL80211_IFTYPE_STATION
&&
279 ap_sta_id
!= IWL_MVM_INVALID_STA
) {
280 struct iwl_mvm_sta
*mvm_sta
;
282 mvm_sta
= iwl_mvm_sta_from_staid_protected(mvm
, ap_sta_id
);
284 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
285 "ap_sta_id %d - reduced Tx power %d\n",
287 mvm_sta
->bt_reduced_txpower
);
292 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
294 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
295 "idle rx chains %d, active rx chains: %d\n",
296 chanctx_conf
->rx_chains_static
,
297 chanctx_conf
->rx_chains_dynamic
);
300 mutex_unlock(&mvm
->mutex
);
302 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
305 static void iwl_dbgfs_update_bf(struct ieee80211_vif
*vif
,
306 enum iwl_dbgfs_bf_mask param
, int value
)
308 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
309 struct iwl_dbgfs_bf
*dbgfs_bf
= &mvmvif
->dbgfs_bf
;
311 dbgfs_bf
->mask
|= param
;
314 case MVM_DEBUGFS_BF_ENERGY_DELTA
:
315 dbgfs_bf
->bf_energy_delta
= value
;
317 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
318 dbgfs_bf
->bf_roaming_energy_delta
= value
;
320 case MVM_DEBUGFS_BF_ROAMING_STATE
:
321 dbgfs_bf
->bf_roaming_state
= value
;
323 case MVM_DEBUGFS_BF_TEMP_THRESHOLD
:
324 dbgfs_bf
->bf_temp_threshold
= value
;
326 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER
:
327 dbgfs_bf
->bf_temp_fast_filter
= value
;
329 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
:
330 dbgfs_bf
->bf_temp_slow_filter
= value
;
332 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
333 dbgfs_bf
->bf_enable_beacon_filter
= value
;
335 case MVM_DEBUGFS_BF_DEBUG_FLAG
:
336 dbgfs_bf
->bf_debug_flag
= value
;
338 case MVM_DEBUGFS_BF_ESCAPE_TIMER
:
339 dbgfs_bf
->bf_escape_timer
= value
;
341 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
342 dbgfs_bf
->ba_enable_beacon_abort
= value
;
344 case MVM_DEBUGFS_BA_ESCAPE_TIMER
:
345 dbgfs_bf
->ba_escape_timer
= value
;
350 static ssize_t
iwl_dbgfs_bf_params_write(struct ieee80211_vif
*vif
, char *buf
,
351 size_t count
, loff_t
*ppos
)
353 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
354 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
355 enum iwl_dbgfs_bf_mask param
;
358 if (!strncmp("bf_energy_delta=", buf
, 16)) {
359 if (sscanf(buf
+16, "%d", &value
) != 1)
361 if (value
< IWL_BF_ENERGY_DELTA_MIN
||
362 value
> IWL_BF_ENERGY_DELTA_MAX
)
364 param
= MVM_DEBUGFS_BF_ENERGY_DELTA
;
365 } else if (!strncmp("bf_roaming_energy_delta=", buf
, 24)) {
366 if (sscanf(buf
+24, "%d", &value
) != 1)
368 if (value
< IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
369 value
> IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
371 param
= MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
372 } else if (!strncmp("bf_roaming_state=", buf
, 17)) {
373 if (sscanf(buf
+17, "%d", &value
) != 1)
375 if (value
< IWL_BF_ROAMING_STATE_MIN
||
376 value
> IWL_BF_ROAMING_STATE_MAX
)
378 param
= MVM_DEBUGFS_BF_ROAMING_STATE
;
379 } else if (!strncmp("bf_temp_threshold=", buf
, 18)) {
380 if (sscanf(buf
+18, "%d", &value
) != 1)
382 if (value
< IWL_BF_TEMP_THRESHOLD_MIN
||
383 value
> IWL_BF_TEMP_THRESHOLD_MAX
)
385 param
= MVM_DEBUGFS_BF_TEMP_THRESHOLD
;
386 } else if (!strncmp("bf_temp_fast_filter=", buf
, 20)) {
387 if (sscanf(buf
+20, "%d", &value
) != 1)
389 if (value
< IWL_BF_TEMP_FAST_FILTER_MIN
||
390 value
> IWL_BF_TEMP_FAST_FILTER_MAX
)
392 param
= MVM_DEBUGFS_BF_TEMP_FAST_FILTER
;
393 } else if (!strncmp("bf_temp_slow_filter=", buf
, 20)) {
394 if (sscanf(buf
+20, "%d", &value
) != 1)
396 if (value
< IWL_BF_TEMP_SLOW_FILTER_MIN
||
397 value
> IWL_BF_TEMP_SLOW_FILTER_MAX
)
399 param
= MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
;
400 } else if (!strncmp("bf_enable_beacon_filter=", buf
, 24)) {
401 if (sscanf(buf
+24, "%d", &value
) != 1)
403 if (value
< 0 || value
> 1)
405 param
= MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
406 } else if (!strncmp("bf_debug_flag=", buf
, 14)) {
407 if (sscanf(buf
+14, "%d", &value
) != 1)
409 if (value
< 0 || value
> 1)
411 param
= MVM_DEBUGFS_BF_DEBUG_FLAG
;
412 } else if (!strncmp("bf_escape_timer=", buf
, 16)) {
413 if (sscanf(buf
+16, "%d", &value
) != 1)
415 if (value
< IWL_BF_ESCAPE_TIMER_MIN
||
416 value
> IWL_BF_ESCAPE_TIMER_MAX
)
418 param
= MVM_DEBUGFS_BF_ESCAPE_TIMER
;
419 } else if (!strncmp("ba_escape_timer=", buf
, 16)) {
420 if (sscanf(buf
+16, "%d", &value
) != 1)
422 if (value
< IWL_BA_ESCAPE_TIMER_MIN
||
423 value
> IWL_BA_ESCAPE_TIMER_MAX
)
425 param
= MVM_DEBUGFS_BA_ESCAPE_TIMER
;
426 } else if (!strncmp("ba_enable_beacon_abort=", buf
, 23)) {
427 if (sscanf(buf
+23, "%d", &value
) != 1)
429 if (value
< 0 || value
> 1)
431 param
= MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
436 mutex_lock(&mvm
->mutex
);
437 iwl_dbgfs_update_bf(vif
, param
, value
);
438 if (param
== MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&& !value
)
439 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
, 0);
441 ret
= iwl_mvm_enable_beacon_filter(mvm
, vif
, 0);
442 mutex_unlock(&mvm
->mutex
);
447 static ssize_t
iwl_dbgfs_bf_params_read(struct file
*file
,
448 char __user
*user_buf
,
449 size_t count
, loff_t
*ppos
)
451 struct ieee80211_vif
*vif
= file
->private_data
;
452 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
455 const size_t bufsz
= sizeof(buf
);
456 struct iwl_beacon_filter_cmd cmd
= {
457 IWL_BF_CMD_CONFIG_DEFAULTS
,
458 .bf_enable_beacon_filter
=
459 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
),
460 .ba_enable_beacon_abort
=
461 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
),
464 iwl_mvm_beacon_filter_debugfs_parameters(vif
, &cmd
);
465 if (mvmvif
->bf_data
.bf_enabled
)
466 cmd
.bf_enable_beacon_filter
= cpu_to_le32(1);
468 cmd
.bf_enable_beacon_filter
= 0;
470 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_energy_delta = %d\n",
471 le32_to_cpu(cmd
.bf_energy_delta
));
472 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_energy_delta = %d\n",
473 le32_to_cpu(cmd
.bf_roaming_energy_delta
));
474 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_state = %d\n",
475 le32_to_cpu(cmd
.bf_roaming_state
));
476 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_threshold = %d\n",
477 le32_to_cpu(cmd
.bf_temp_threshold
));
478 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_fast_filter = %d\n",
479 le32_to_cpu(cmd
.bf_temp_fast_filter
));
480 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_slow_filter = %d\n",
481 le32_to_cpu(cmd
.bf_temp_slow_filter
));
482 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_enable_beacon_filter = %d\n",
483 le32_to_cpu(cmd
.bf_enable_beacon_filter
));
484 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_debug_flag = %d\n",
485 le32_to_cpu(cmd
.bf_debug_flag
));
486 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_escape_timer = %d\n",
487 le32_to_cpu(cmd
.bf_escape_timer
));
488 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_escape_timer = %d\n",
489 le32_to_cpu(cmd
.ba_escape_timer
));
490 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_enable_beacon_abort = %d\n",
491 le32_to_cpu(cmd
.ba_enable_beacon_abort
));
493 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
496 static inline char *iwl_dbgfs_is_match(char *name
, char *buf
)
498 int len
= strlen(name
);
500 return !strncmp(name
, buf
, len
) ? buf
+ len
: NULL
;
503 static ssize_t
iwl_dbgfs_os_device_timediff_read(struct file
*file
,
504 char __user
*user_buf
,
505 size_t count
, loff_t
*ppos
)
507 struct ieee80211_vif
*vif
= file
->private_data
;
508 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
509 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
514 const size_t bufsz
= sizeof(buf
);
517 iwl_mvm_get_sync_time(mvm
, &curr_gp2
, &curr_os
);
518 do_div(curr_os
, NSEC_PER_USEC
);
519 diff
= curr_os
- curr_gp2
;
520 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "diff=%lld\n", diff
);
522 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
525 static ssize_t
iwl_dbgfs_low_latency_write(struct ieee80211_vif
*vif
, char *buf
,
526 size_t count
, loff_t
*ppos
)
528 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
529 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
533 ret
= kstrtou8(buf
, 0, &value
);
539 mutex_lock(&mvm
->mutex
);
540 iwl_mvm_update_low_latency(mvm
, vif
, value
, LOW_LATENCY_DEBUGFS
);
541 mutex_unlock(&mvm
->mutex
);
547 iwl_dbgfs_low_latency_force_write(struct ieee80211_vif
*vif
, char *buf
,
548 size_t count
, loff_t
*ppos
)
550 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
551 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
555 ret
= kstrtou8(buf
, 0, &value
);
559 if (value
> NUM_LOW_LATENCY_FORCE
)
562 mutex_lock(&mvm
->mutex
);
563 if (value
== LOW_LATENCY_FORCE_UNSET
) {
564 iwl_mvm_update_low_latency(mvm
, vif
, false,
565 LOW_LATENCY_DEBUGFS_FORCE
);
566 iwl_mvm_update_low_latency(mvm
, vif
, false,
567 LOW_LATENCY_DEBUGFS_FORCE_ENABLE
);
569 iwl_mvm_update_low_latency(mvm
, vif
,
570 value
== LOW_LATENCY_FORCE_ON
,
571 LOW_LATENCY_DEBUGFS_FORCE
);
572 iwl_mvm_update_low_latency(mvm
, vif
, true,
573 LOW_LATENCY_DEBUGFS_FORCE_ENABLE
);
575 mutex_unlock(&mvm
->mutex
);
579 static ssize_t
iwl_dbgfs_low_latency_read(struct file
*file
,
580 char __user
*user_buf
,
581 size_t count
, loff_t
*ppos
)
583 struct ieee80211_vif
*vif
= file
->private_data
;
584 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
585 char format
[] = "traffic=%d\ndbgfs=%d\nvcmd=%d\nvif_type=%d\n"
586 "dbgfs_force_enable=%d\ndbgfs_force=%d\nactual=%d\n";
589 * all values in format are boolean so the size of format is enough
590 * for holding the result string
592 char buf
[sizeof(format
) + 1] = {};
595 len
= scnprintf(buf
, sizeof(buf
) - 1, format
,
596 !!(mvmvif
->low_latency
& LOW_LATENCY_TRAFFIC
),
597 !!(mvmvif
->low_latency
& LOW_LATENCY_DEBUGFS
),
598 !!(mvmvif
->low_latency
& LOW_LATENCY_VCMD
),
599 !!(mvmvif
->low_latency
& LOW_LATENCY_VIF_TYPE
),
600 !!(mvmvif
->low_latency
&
601 LOW_LATENCY_DEBUGFS_FORCE_ENABLE
),
602 !!(mvmvif
->low_latency
& LOW_LATENCY_DEBUGFS_FORCE
),
603 !!(mvmvif
->low_latency_actual
));
604 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
607 static ssize_t
iwl_dbgfs_uapsd_misbehaving_read(struct file
*file
,
608 char __user
*user_buf
,
609 size_t count
, loff_t
*ppos
)
611 struct ieee80211_vif
*vif
= file
->private_data
;
612 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
616 len
= sprintf(buf
, "%pM\n", mvmvif
->uapsd_misbehaving_bssid
);
617 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
620 static ssize_t
iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif
*vif
,
621 char *buf
, size_t count
,
624 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
625 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
628 mutex_lock(&mvm
->mutex
);
629 ret
= mac_pton(buf
, mvmvif
->uapsd_misbehaving_bssid
);
630 mutex_unlock(&mvm
->mutex
);
632 return ret
? count
: -EINVAL
;
635 static ssize_t
iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif
*vif
, char *buf
,
636 size_t count
, loff_t
*ppos
)
638 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
639 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
640 struct ieee80211_chanctx_conf
*chanctx_conf
;
641 struct iwl_mvm_phy_ctxt
*phy_ctxt
;
645 ret
= kstrtou16(buf
, 0, &value
);
649 mutex_lock(&mvm
->mutex
);
652 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
653 /* make sure the channel context is assigned */
656 mutex_unlock(&mvm
->mutex
);
660 phy_ctxt
= &mvm
->phy_ctxts
[*(u16
*)chanctx_conf
->drv_priv
];
663 mvm
->dbgfs_rx_phyinfo
= value
;
665 ret
= iwl_mvm_phy_ctxt_changed(mvm
, phy_ctxt
, &chanctx_conf
->min_def
,
666 chanctx_conf
->rx_chains_static
,
667 chanctx_conf
->rx_chains_dynamic
);
668 mutex_unlock(&mvm
->mutex
);
673 static ssize_t
iwl_dbgfs_rx_phyinfo_read(struct file
*file
,
674 char __user
*user_buf
,
675 size_t count
, loff_t
*ppos
)
677 struct ieee80211_vif
*vif
= file
->private_data
;
678 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
682 len
= scnprintf(buf
, sizeof(buf
), "0x%04x\n",
683 mvmvif
->mvm
->dbgfs_rx_phyinfo
);
685 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
688 static void iwl_dbgfs_quota_check(void *data
, u8
*mac
,
689 struct ieee80211_vif
*vif
)
691 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
694 if (mvmvif
->dbgfs_quota_min
)
698 static ssize_t
iwl_dbgfs_quota_min_write(struct ieee80211_vif
*vif
, char *buf
,
699 size_t count
, loff_t
*ppos
)
701 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
702 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
706 ret
= kstrtou16(buf
, 0, &value
);
713 mutex_lock(&mvm
->mutex
);
715 mvmvif
->dbgfs_quota_min
= 0;
716 ieee80211_iterate_interfaces(mvm
->hw
, IEEE80211_IFACE_ITER_NORMAL
,
717 iwl_dbgfs_quota_check
, &ret
);
719 mvmvif
->dbgfs_quota_min
= value
;
720 iwl_mvm_update_quotas(mvm
, false, NULL
);
722 mutex_unlock(&mvm
->mutex
);
727 static ssize_t
iwl_dbgfs_quota_min_read(struct file
*file
,
728 char __user
*user_buf
,
729 size_t count
, loff_t
*ppos
)
731 struct ieee80211_vif
*vif
= file
->private_data
;
732 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
736 len
= scnprintf(buf
, sizeof(buf
), "%d\n", mvmvif
->dbgfs_quota_min
);
738 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
741 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
742 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
743 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
744 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
745 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
746 debugfs_create_file(#name, mode, parent, vif, \
747 &iwl_dbgfs_##name##_ops); \
750 MVM_DEBUGFS_READ_FILE_OPS(mac_params
);
751 MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt
);
752 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params
, 32);
753 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params
, 256);
754 MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency
, 10);
755 MVM_DEBUGFS_WRITE_FILE_OPS(low_latency_force
, 10);
756 MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving
, 20);
757 MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo
, 10);
758 MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min
, 32);
759 MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff
);
762 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
764 struct dentry
*dbgfs_dir
= vif
->debugfs_dir
;
765 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
769 * Check if debugfs directory already exist before creating it.
770 * This may happen when, for example, resetting hw or suspend-resume
772 if (!dbgfs_dir
|| mvmvif
->dbgfs_dir
)
775 mvmvif
->dbgfs_dir
= debugfs_create_dir("iwlmvm", dbgfs_dir
);
776 if (IS_ERR_OR_NULL(mvmvif
->dbgfs_dir
)) {
777 IWL_ERR(mvm
, "Failed to create debugfs directory under %pd\n",
782 if (iwlmvm_mod_params
.power_scheme
!= IWL_POWER_SCHEME_CAM
&&
783 ((vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
) ||
784 (vif
->type
== NL80211_IFTYPE_STATION
&& vif
->p2p
)))
785 MVM_DEBUGFS_ADD_FILE_VIF(pm_params
, mvmvif
->dbgfs_dir
, 0600);
787 MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt
, mvmvif
->dbgfs_dir
, 0400);
788 MVM_DEBUGFS_ADD_FILE_VIF(mac_params
, mvmvif
->dbgfs_dir
, 0400);
789 MVM_DEBUGFS_ADD_FILE_VIF(low_latency
, mvmvif
->dbgfs_dir
, 0600);
790 MVM_DEBUGFS_ADD_FILE_VIF(low_latency_force
, mvmvif
->dbgfs_dir
, 0600);
791 MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving
, mvmvif
->dbgfs_dir
, 0600);
792 MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo
, mvmvif
->dbgfs_dir
, 0600);
793 MVM_DEBUGFS_ADD_FILE_VIF(quota_min
, mvmvif
->dbgfs_dir
, 0600);
794 MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff
, mvmvif
->dbgfs_dir
, 0400);
796 if (vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
797 mvmvif
== mvm
->bf_allowed_vif
)
798 MVM_DEBUGFS_ADD_FILE_VIF(bf_params
, mvmvif
->dbgfs_dir
, 0600);
801 * Create symlink for convenience pointing to interface specific
802 * debugfs entries for the driver. For example, under
803 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
805 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
807 snprintf(buf
, 100, "../../../%pd3/%pd",
811 mvmvif
->dbgfs_slink
= debugfs_create_symlink(dbgfs_dir
->d_name
.name
,
812 mvm
->debugfs_dir
, buf
);
815 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
817 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
819 debugfs_remove(mvmvif
->dbgfs_slink
);
820 mvmvif
->dbgfs_slink
= NULL
;
822 debugfs_remove_recursive(mvmvif
->dbgfs_dir
);
823 mvmvif
->dbgfs_dir
= NULL
;