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.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
24 * The full GNU General Public License is included in this distribution
25 * in the file called COPYING.
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
33 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 *****************************************************************************/
66 static void iwl_dbgfs_update_pm(struct iwl_mvm
*mvm
,
67 struct ieee80211_vif
*vif
,
68 enum iwl_dbgfs_pm_mask param
, int val
)
70 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
71 struct iwl_dbgfs_pm
*dbgfs_pm
= &mvmvif
->dbgfs_pm
;
73 dbgfs_pm
->mask
|= param
;
76 case MVM_DEBUGFS_PM_KEEP_ALIVE
: {
77 struct ieee80211_hw
*hw
= mvm
->hw
;
78 int dtimper
= hw
->conf
.ps_dtim_period
?: 1;
79 int dtimper_msec
= dtimper
* vif
->bss_conf
.beacon_int
;
81 IWL_DEBUG_POWER(mvm
, "debugfs: set keep_alive= %d sec\n", val
);
82 if (val
* MSEC_PER_SEC
< 3 * dtimper_msec
)
84 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
85 val
* MSEC_PER_SEC
, 3 * dtimper_msec
);
86 dbgfs_pm
->keep_alive_seconds
= val
;
89 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM
:
90 IWL_DEBUG_POWER(mvm
, "skip_over_dtim %s\n",
91 val
? "enabled" : "disabled");
92 dbgfs_pm
->skip_over_dtim
= val
;
94 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
:
95 IWL_DEBUG_POWER(mvm
, "skip_dtim_periods=%d\n", val
);
96 dbgfs_pm
->skip_dtim_periods
= val
;
98 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
:
99 IWL_DEBUG_POWER(mvm
, "rx_data_timeout=%d\n", val
);
100 dbgfs_pm
->rx_data_timeout
= val
;
102 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
:
103 IWL_DEBUG_POWER(mvm
, "tx_data_timeout=%d\n", val
);
104 dbgfs_pm
->tx_data_timeout
= val
;
106 case MVM_DEBUGFS_PM_DISABLE_POWER_OFF
:
107 IWL_DEBUG_POWER(mvm
, "disable_power_off=%d\n", val
);
108 dbgfs_pm
->disable_power_off
= 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
;
129 static ssize_t
iwl_dbgfs_pm_params_write(struct ieee80211_vif
*vif
, char *buf
,
130 size_t count
, loff_t
*ppos
)
132 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
133 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
134 enum iwl_dbgfs_pm_mask param
;
137 if (!strncmp("keep_alive=", buf
, 11)) {
138 if (sscanf(buf
+ 11, "%d", &val
) != 1)
140 param
= MVM_DEBUGFS_PM_KEEP_ALIVE
;
141 } else if (!strncmp("skip_over_dtim=", buf
, 15)) {
142 if (sscanf(buf
+ 15, "%d", &val
) != 1)
144 param
= MVM_DEBUGFS_PM_SKIP_OVER_DTIM
;
145 } else if (!strncmp("skip_dtim_periods=", buf
, 18)) {
146 if (sscanf(buf
+ 18, "%d", &val
) != 1)
148 param
= MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
;
149 } else if (!strncmp("rx_data_timeout=", buf
, 16)) {
150 if (sscanf(buf
+ 16, "%d", &val
) != 1)
152 param
= MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
;
153 } else if (!strncmp("tx_data_timeout=", buf
, 16)) {
154 if (sscanf(buf
+ 16, "%d", &val
) != 1)
156 param
= MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
;
157 } else if (!strncmp("disable_power_off=", buf
, 18) &&
158 !(mvm
->fw
->ucode_capa
.flags
&
159 IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD
)) {
160 if (sscanf(buf
+ 18, "%d", &val
) != 1)
162 param
= MVM_DEBUGFS_PM_DISABLE_POWER_OFF
;
163 } else if (!strncmp("lprx=", buf
, 5)) {
164 if (sscanf(buf
+ 5, "%d", &val
) != 1)
166 param
= MVM_DEBUGFS_PM_LPRX_ENA
;
167 } else if (!strncmp("lprx_rssi_threshold=", buf
, 20)) {
168 if (sscanf(buf
+ 20, "%d", &val
) != 1)
170 if (val
> POWER_LPRX_RSSI_THRESHOLD_MAX
|| val
<
171 POWER_LPRX_RSSI_THRESHOLD_MIN
)
173 param
= MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
;
174 } else if (!strncmp("snooze_enable=", buf
, 14)) {
175 if (sscanf(buf
+ 14, "%d", &val
) != 1)
177 param
= MVM_DEBUGFS_PM_SNOOZE_ENABLE
;
178 } else if (!strncmp("uapsd_misbehaving=", buf
, 18)) {
179 if (sscanf(buf
+ 18, "%d", &val
) != 1)
181 param
= MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
;
186 mutex_lock(&mvm
->mutex
);
187 iwl_dbgfs_update_pm(mvm
, vif
, param
, val
);
188 ret
= iwl_mvm_power_update_mode(mvm
, vif
);
189 mutex_unlock(&mvm
->mutex
);
194 static ssize_t
iwl_dbgfs_pm_params_read(struct file
*file
,
195 char __user
*user_buf
,
196 size_t count
, loff_t
*ppos
)
198 struct ieee80211_vif
*vif
= file
->private_data
;
199 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
200 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
202 int bufsz
= sizeof(buf
);
205 pos
= iwl_mvm_power_dbgfs_read(mvm
, vif
, buf
, bufsz
);
207 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
210 static ssize_t
iwl_dbgfs_mac_params_read(struct file
*file
,
211 char __user
*user_buf
,
212 size_t count
, loff_t
*ppos
)
214 struct ieee80211_vif
*vif
= file
->private_data
;
215 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
216 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
218 struct ieee80211_chanctx_conf
*chanctx_conf
;
220 int bufsz
= sizeof(buf
);
224 mutex_lock(&mvm
->mutex
);
226 ap_sta_id
= mvmvif
->ap_sta_id
;
228 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "mac id/color: %d / %d\n",
229 mvmvif
->id
, mvmvif
->color
);
230 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bssid: %pM\n",
231 vif
->bss_conf
.bssid
);
232 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "QoS:\n");
233 for (i
= 0; i
< ARRAY_SIZE(mvmvif
->queue_params
); i
++)
234 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
235 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
236 i
, mvmvif
->queue_params
[i
].txop
,
237 mvmvif
->queue_params
[i
].cw_min
,
238 mvmvif
->queue_params
[i
].cw_max
,
239 mvmvif
->queue_params
[i
].aifs
,
240 mvmvif
->queue_params
[i
].uapsd
);
242 if (vif
->type
== NL80211_IFTYPE_STATION
&&
243 ap_sta_id
!= IWL_MVM_STATION_COUNT
) {
244 struct ieee80211_sta
*sta
;
246 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[ap_sta_id
],
247 lockdep_is_held(&mvm
->mutex
));
248 if (!IS_ERR_OR_NULL(sta
)) {
249 struct iwl_mvm_sta
*mvm_sta
= (void *)sta
->drv_priv
;
251 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
252 "ap_sta_id %d - reduced Tx power %d\n",
254 mvm_sta
->bt_reduced_txpower
);
259 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
261 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
262 "idle rx chains %d, active rx chains: %d\n",
263 chanctx_conf
->rx_chains_static
,
264 chanctx_conf
->rx_chains_dynamic
);
267 mutex_unlock(&mvm
->mutex
);
269 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
272 static void iwl_dbgfs_update_bf(struct ieee80211_vif
*vif
,
273 enum iwl_dbgfs_bf_mask param
, int value
)
275 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
276 struct iwl_dbgfs_bf
*dbgfs_bf
= &mvmvif
->dbgfs_bf
;
278 dbgfs_bf
->mask
|= param
;
281 case MVM_DEBUGFS_BF_ENERGY_DELTA
:
282 dbgfs_bf
->bf_energy_delta
= value
;
284 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
285 dbgfs_bf
->bf_roaming_energy_delta
= value
;
287 case MVM_DEBUGFS_BF_ROAMING_STATE
:
288 dbgfs_bf
->bf_roaming_state
= value
;
290 case MVM_DEBUGFS_BF_TEMP_THRESHOLD
:
291 dbgfs_bf
->bf_temp_threshold
= value
;
293 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER
:
294 dbgfs_bf
->bf_temp_fast_filter
= value
;
296 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
:
297 dbgfs_bf
->bf_temp_slow_filter
= value
;
299 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
300 dbgfs_bf
->bf_enable_beacon_filter
= value
;
302 case MVM_DEBUGFS_BF_DEBUG_FLAG
:
303 dbgfs_bf
->bf_debug_flag
= value
;
305 case MVM_DEBUGFS_BF_ESCAPE_TIMER
:
306 dbgfs_bf
->bf_escape_timer
= value
;
308 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
309 dbgfs_bf
->ba_enable_beacon_abort
= value
;
311 case MVM_DEBUGFS_BA_ESCAPE_TIMER
:
312 dbgfs_bf
->ba_escape_timer
= value
;
317 static ssize_t
iwl_dbgfs_bf_params_write(struct ieee80211_vif
*vif
, char *buf
,
318 size_t count
, loff_t
*ppos
)
320 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
321 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
322 enum iwl_dbgfs_bf_mask param
;
325 if (!strncmp("bf_energy_delta=", buf
, 16)) {
326 if (sscanf(buf
+16, "%d", &value
) != 1)
328 if (value
< IWL_BF_ENERGY_DELTA_MIN
||
329 value
> IWL_BF_ENERGY_DELTA_MAX
)
331 param
= MVM_DEBUGFS_BF_ENERGY_DELTA
;
332 } else if (!strncmp("bf_roaming_energy_delta=", buf
, 24)) {
333 if (sscanf(buf
+24, "%d", &value
) != 1)
335 if (value
< IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
336 value
> IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
338 param
= MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
339 } else if (!strncmp("bf_roaming_state=", buf
, 17)) {
340 if (sscanf(buf
+17, "%d", &value
) != 1)
342 if (value
< IWL_BF_ROAMING_STATE_MIN
||
343 value
> IWL_BF_ROAMING_STATE_MAX
)
345 param
= MVM_DEBUGFS_BF_ROAMING_STATE
;
346 } else if (!strncmp("bf_temp_threshold=", buf
, 18)) {
347 if (sscanf(buf
+18, "%d", &value
) != 1)
349 if (value
< IWL_BF_TEMP_THRESHOLD_MIN
||
350 value
> IWL_BF_TEMP_THRESHOLD_MAX
)
352 param
= MVM_DEBUGFS_BF_TEMP_THRESHOLD
;
353 } else if (!strncmp("bf_temp_fast_filter=", buf
, 20)) {
354 if (sscanf(buf
+20, "%d", &value
) != 1)
356 if (value
< IWL_BF_TEMP_FAST_FILTER_MIN
||
357 value
> IWL_BF_TEMP_FAST_FILTER_MAX
)
359 param
= MVM_DEBUGFS_BF_TEMP_FAST_FILTER
;
360 } else if (!strncmp("bf_temp_slow_filter=", buf
, 20)) {
361 if (sscanf(buf
+20, "%d", &value
) != 1)
363 if (value
< IWL_BF_TEMP_SLOW_FILTER_MIN
||
364 value
> IWL_BF_TEMP_SLOW_FILTER_MAX
)
366 param
= MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
;
367 } else if (!strncmp("bf_enable_beacon_filter=", buf
, 24)) {
368 if (sscanf(buf
+24, "%d", &value
) != 1)
370 if (value
< 0 || value
> 1)
372 param
= MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
373 } else if (!strncmp("bf_debug_flag=", buf
, 14)) {
374 if (sscanf(buf
+14, "%d", &value
) != 1)
376 if (value
< 0 || value
> 1)
378 param
= MVM_DEBUGFS_BF_DEBUG_FLAG
;
379 } else if (!strncmp("bf_escape_timer=", buf
, 16)) {
380 if (sscanf(buf
+16, "%d", &value
) != 1)
382 if (value
< IWL_BF_ESCAPE_TIMER_MIN
||
383 value
> IWL_BF_ESCAPE_TIMER_MAX
)
385 param
= MVM_DEBUGFS_BF_ESCAPE_TIMER
;
386 } else if (!strncmp("ba_escape_timer=", buf
, 16)) {
387 if (sscanf(buf
+16, "%d", &value
) != 1)
389 if (value
< IWL_BA_ESCAPE_TIMER_MIN
||
390 value
> IWL_BA_ESCAPE_TIMER_MAX
)
392 param
= MVM_DEBUGFS_BA_ESCAPE_TIMER
;
393 } else if (!strncmp("ba_enable_beacon_abort=", buf
, 23)) {
394 if (sscanf(buf
+23, "%d", &value
) != 1)
396 if (value
< 0 || value
> 1)
398 param
= MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
403 mutex_lock(&mvm
->mutex
);
404 iwl_dbgfs_update_bf(vif
, param
, value
);
405 if (param
== MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&& !value
)
406 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
);
408 ret
= iwl_mvm_enable_beacon_filter(mvm
, vif
);
409 mutex_unlock(&mvm
->mutex
);
414 static ssize_t
iwl_dbgfs_bf_params_read(struct file
*file
,
415 char __user
*user_buf
,
416 size_t count
, loff_t
*ppos
)
418 struct ieee80211_vif
*vif
= file
->private_data
;
419 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
422 const size_t bufsz
= sizeof(buf
);
423 struct iwl_beacon_filter_cmd cmd
= {
424 IWL_BF_CMD_CONFIG_DEFAULTS
,
425 .bf_enable_beacon_filter
=
426 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
),
427 .ba_enable_beacon_abort
=
428 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
),
431 iwl_mvm_beacon_filter_debugfs_parameters(vif
, &cmd
);
432 if (mvmvif
->bf_data
.bf_enabled
)
433 cmd
.bf_enable_beacon_filter
= cpu_to_le32(1);
435 cmd
.bf_enable_beacon_filter
= 0;
437 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_energy_delta = %d\n",
438 le32_to_cpu(cmd
.bf_energy_delta
));
439 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_energy_delta = %d\n",
440 le32_to_cpu(cmd
.bf_roaming_energy_delta
));
441 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_state = %d\n",
442 le32_to_cpu(cmd
.bf_roaming_state
));
443 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_threshold = %d\n",
444 le32_to_cpu(cmd
.bf_temp_threshold
));
445 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_fast_filter = %d\n",
446 le32_to_cpu(cmd
.bf_temp_fast_filter
));
447 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_slow_filter = %d\n",
448 le32_to_cpu(cmd
.bf_temp_slow_filter
));
449 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_enable_beacon_filter = %d\n",
450 le32_to_cpu(cmd
.bf_enable_beacon_filter
));
451 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_debug_flag = %d\n",
452 le32_to_cpu(cmd
.bf_debug_flag
));
453 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_escape_timer = %d\n",
454 le32_to_cpu(cmd
.bf_escape_timer
));
455 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_escape_timer = %d\n",
456 le32_to_cpu(cmd
.ba_escape_timer
));
457 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_enable_beacon_abort = %d\n",
458 le32_to_cpu(cmd
.ba_enable_beacon_abort
));
460 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
463 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
464 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
465 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
466 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
467 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
468 if (!debugfs_create_file(#name, mode, parent, vif, \
469 &iwl_dbgfs_##name##_ops)) \
473 MVM_DEBUGFS_READ_FILE_OPS(mac_params
);
474 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params
, 32);
475 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params
, 256);
477 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
479 struct dentry
*dbgfs_dir
= vif
->debugfs_dir
;
480 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
484 * Check if debugfs directory already exist before creating it.
485 * This may happen when, for example, resetting hw or suspend-resume
487 if (!dbgfs_dir
|| mvmvif
->dbgfs_dir
)
490 mvmvif
->dbgfs_dir
= debugfs_create_dir("iwlmvm", dbgfs_dir
);
493 if (!mvmvif
->dbgfs_dir
) {
494 IWL_ERR(mvm
, "Failed to create debugfs directory under %s\n",
495 dbgfs_dir
->d_name
.name
);
499 if (iwlmvm_mod_params
.power_scheme
!= IWL_POWER_SCHEME_CAM
&&
500 ((vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
) ||
501 (vif
->type
== NL80211_IFTYPE_STATION
&& vif
->p2p
&&
502 mvm
->fw
->ucode_capa
.flags
& IWL_UCODE_TLV_FLAGS_P2P_PS
)))
503 MVM_DEBUGFS_ADD_FILE_VIF(pm_params
, mvmvif
->dbgfs_dir
, S_IWUSR
|
506 MVM_DEBUGFS_ADD_FILE_VIF(mac_params
, mvmvif
->dbgfs_dir
,
509 if (vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
510 mvmvif
== mvm
->bf_allowed_vif
)
511 MVM_DEBUGFS_ADD_FILE_VIF(bf_params
, mvmvif
->dbgfs_dir
,
515 * Create symlink for convenience pointing to interface specific
516 * debugfs entries for the driver. For example, under
517 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
519 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
521 snprintf(buf
, 100, "../../../%s/%s/%s/%s",
522 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
523 dbgfs_dir
->d_parent
->d_name
.name
,
524 dbgfs_dir
->d_name
.name
,
525 mvmvif
->dbgfs_dir
->d_name
.name
);
527 mvmvif
->dbgfs_slink
= debugfs_create_symlink(dbgfs_dir
->d_name
.name
,
528 mvm
->debugfs_dir
, buf
);
529 if (!mvmvif
->dbgfs_slink
)
530 IWL_ERR(mvm
, "Can't create debugfs symbolic link under %s\n",
531 dbgfs_dir
->d_name
.name
);
534 IWL_ERR(mvm
, "Can't create debugfs entity\n");
537 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
539 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
541 debugfs_remove(mvmvif
->dbgfs_slink
);
542 mvmvif
->dbgfs_slink
= NULL
;
544 debugfs_remove_recursive(mvmvif
->dbgfs_dir
);
545 mvmvif
->dbgfs_dir
= NULL
;