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_LPRX_ENA
:
107 IWL_DEBUG_POWER(mvm
, "lprx %s\n", val
? "enabled" : "disabled");
108 dbgfs_pm
->lprx_ena
= val
;
110 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
:
111 IWL_DEBUG_POWER(mvm
, "lprx_rssi_threshold=%d\n", val
);
112 dbgfs_pm
->lprx_rssi_threshold
= val
;
114 case MVM_DEBUGFS_PM_SNOOZE_ENABLE
:
115 IWL_DEBUG_POWER(mvm
, "snooze_enable=%d\n", val
);
116 dbgfs_pm
->snooze_ena
= val
;
118 case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
:
119 IWL_DEBUG_POWER(mvm
, "uapsd_misbehaving_enable=%d\n", val
);
120 dbgfs_pm
->uapsd_misbehaving
= val
;
125 static ssize_t
iwl_dbgfs_pm_params_write(struct ieee80211_vif
*vif
, char *buf
,
126 size_t count
, loff_t
*ppos
)
128 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
129 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
130 enum iwl_dbgfs_pm_mask param
;
133 if (!strncmp("keep_alive=", buf
, 11)) {
134 if (sscanf(buf
+ 11, "%d", &val
) != 1)
136 param
= MVM_DEBUGFS_PM_KEEP_ALIVE
;
137 } else if (!strncmp("skip_over_dtim=", buf
, 15)) {
138 if (sscanf(buf
+ 15, "%d", &val
) != 1)
140 param
= MVM_DEBUGFS_PM_SKIP_OVER_DTIM
;
141 } else if (!strncmp("skip_dtim_periods=", buf
, 18)) {
142 if (sscanf(buf
+ 18, "%d", &val
) != 1)
144 param
= MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
;
145 } else if (!strncmp("rx_data_timeout=", buf
, 16)) {
146 if (sscanf(buf
+ 16, "%d", &val
) != 1)
148 param
= MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
;
149 } else if (!strncmp("tx_data_timeout=", buf
, 16)) {
150 if (sscanf(buf
+ 16, "%d", &val
) != 1)
152 param
= MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
;
153 } else if (!strncmp("lprx=", buf
, 5)) {
154 if (sscanf(buf
+ 5, "%d", &val
) != 1)
156 param
= MVM_DEBUGFS_PM_LPRX_ENA
;
157 } else if (!strncmp("lprx_rssi_threshold=", buf
, 20)) {
158 if (sscanf(buf
+ 20, "%d", &val
) != 1)
160 if (val
> POWER_LPRX_RSSI_THRESHOLD_MAX
|| val
<
161 POWER_LPRX_RSSI_THRESHOLD_MIN
)
163 param
= MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
;
164 } else if (!strncmp("snooze_enable=", buf
, 14)) {
165 if (sscanf(buf
+ 14, "%d", &val
) != 1)
167 param
= MVM_DEBUGFS_PM_SNOOZE_ENABLE
;
168 } else if (!strncmp("uapsd_misbehaving=", buf
, 18)) {
169 if (sscanf(buf
+ 18, "%d", &val
) != 1)
171 param
= MVM_DEBUGFS_PM_UAPSD_MISBEHAVING
;
176 mutex_lock(&mvm
->mutex
);
177 iwl_dbgfs_update_pm(mvm
, vif
, param
, val
);
178 ret
= iwl_mvm_power_update_mac(mvm
, vif
);
179 mutex_unlock(&mvm
->mutex
);
184 static ssize_t
iwl_dbgfs_pm_params_read(struct file
*file
,
185 char __user
*user_buf
,
186 size_t count
, loff_t
*ppos
)
188 struct ieee80211_vif
*vif
= file
->private_data
;
189 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
190 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
192 int bufsz
= sizeof(buf
);
195 pos
= iwl_mvm_power_mac_dbgfs_read(mvm
, vif
, buf
, bufsz
);
197 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
200 static ssize_t
iwl_dbgfs_mac_params_read(struct file
*file
,
201 char __user
*user_buf
,
202 size_t count
, loff_t
*ppos
)
204 struct ieee80211_vif
*vif
= file
->private_data
;
205 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
206 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
208 struct ieee80211_chanctx_conf
*chanctx_conf
;
210 int bufsz
= sizeof(buf
);
214 mutex_lock(&mvm
->mutex
);
216 ap_sta_id
= mvmvif
->ap_sta_id
;
218 switch (ieee80211_vif_type_p2p(vif
)) {
219 case NL80211_IFTYPE_ADHOC
:
220 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: ibss\n");
222 case NL80211_IFTYPE_STATION
:
223 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: bss\n");
225 case NL80211_IFTYPE_AP
:
226 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: ap\n");
228 case NL80211_IFTYPE_P2P_CLIENT
:
229 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p client\n");
231 case NL80211_IFTYPE_P2P_GO
:
232 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p go\n");
234 case NL80211_IFTYPE_P2P_DEVICE
:
235 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "type: p2p dev\n");
241 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "mac id/color: %d / %d\n",
242 mvmvif
->id
, mvmvif
->color
);
243 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bssid: %pM\n",
244 vif
->bss_conf
.bssid
);
245 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "QoS:\n");
246 for (i
= 0; i
< ARRAY_SIZE(mvmvif
->queue_params
); i
++)
247 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
248 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
249 i
, mvmvif
->queue_params
[i
].txop
,
250 mvmvif
->queue_params
[i
].cw_min
,
251 mvmvif
->queue_params
[i
].cw_max
,
252 mvmvif
->queue_params
[i
].aifs
,
253 mvmvif
->queue_params
[i
].uapsd
);
255 if (vif
->type
== NL80211_IFTYPE_STATION
&&
256 ap_sta_id
!= IWL_MVM_STATION_COUNT
) {
257 struct ieee80211_sta
*sta
;
259 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[ap_sta_id
],
260 lockdep_is_held(&mvm
->mutex
));
261 if (!IS_ERR_OR_NULL(sta
)) {
262 struct iwl_mvm_sta
*mvm_sta
= (void *)sta
->drv_priv
;
264 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
265 "ap_sta_id %d - reduced Tx power %d\n",
267 mvm_sta
->bt_reduced_txpower
);
272 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
274 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
275 "idle rx chains %d, active rx chains: %d\n",
276 chanctx_conf
->rx_chains_static
,
277 chanctx_conf
->rx_chains_dynamic
);
280 mutex_unlock(&mvm
->mutex
);
282 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
285 static void iwl_dbgfs_update_bf(struct ieee80211_vif
*vif
,
286 enum iwl_dbgfs_bf_mask param
, int value
)
288 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
289 struct iwl_dbgfs_bf
*dbgfs_bf
= &mvmvif
->dbgfs_bf
;
291 dbgfs_bf
->mask
|= param
;
294 case MVM_DEBUGFS_BF_ENERGY_DELTA
:
295 dbgfs_bf
->bf_energy_delta
= value
;
297 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
298 dbgfs_bf
->bf_roaming_energy_delta
= value
;
300 case MVM_DEBUGFS_BF_ROAMING_STATE
:
301 dbgfs_bf
->bf_roaming_state
= value
;
303 case MVM_DEBUGFS_BF_TEMP_THRESHOLD
:
304 dbgfs_bf
->bf_temp_threshold
= value
;
306 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER
:
307 dbgfs_bf
->bf_temp_fast_filter
= value
;
309 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
:
310 dbgfs_bf
->bf_temp_slow_filter
= value
;
312 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
313 dbgfs_bf
->bf_enable_beacon_filter
= value
;
315 case MVM_DEBUGFS_BF_DEBUG_FLAG
:
316 dbgfs_bf
->bf_debug_flag
= value
;
318 case MVM_DEBUGFS_BF_ESCAPE_TIMER
:
319 dbgfs_bf
->bf_escape_timer
= value
;
321 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
322 dbgfs_bf
->ba_enable_beacon_abort
= value
;
324 case MVM_DEBUGFS_BA_ESCAPE_TIMER
:
325 dbgfs_bf
->ba_escape_timer
= value
;
330 static ssize_t
iwl_dbgfs_bf_params_write(struct ieee80211_vif
*vif
, char *buf
,
331 size_t count
, loff_t
*ppos
)
333 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
334 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
335 enum iwl_dbgfs_bf_mask param
;
338 if (!strncmp("bf_energy_delta=", buf
, 16)) {
339 if (sscanf(buf
+16, "%d", &value
) != 1)
341 if (value
< IWL_BF_ENERGY_DELTA_MIN
||
342 value
> IWL_BF_ENERGY_DELTA_MAX
)
344 param
= MVM_DEBUGFS_BF_ENERGY_DELTA
;
345 } else if (!strncmp("bf_roaming_energy_delta=", buf
, 24)) {
346 if (sscanf(buf
+24, "%d", &value
) != 1)
348 if (value
< IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
349 value
> IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
351 param
= MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
352 } else if (!strncmp("bf_roaming_state=", buf
, 17)) {
353 if (sscanf(buf
+17, "%d", &value
) != 1)
355 if (value
< IWL_BF_ROAMING_STATE_MIN
||
356 value
> IWL_BF_ROAMING_STATE_MAX
)
358 param
= MVM_DEBUGFS_BF_ROAMING_STATE
;
359 } else if (!strncmp("bf_temp_threshold=", buf
, 18)) {
360 if (sscanf(buf
+18, "%d", &value
) != 1)
362 if (value
< IWL_BF_TEMP_THRESHOLD_MIN
||
363 value
> IWL_BF_TEMP_THRESHOLD_MAX
)
365 param
= MVM_DEBUGFS_BF_TEMP_THRESHOLD
;
366 } else if (!strncmp("bf_temp_fast_filter=", buf
, 20)) {
367 if (sscanf(buf
+20, "%d", &value
) != 1)
369 if (value
< IWL_BF_TEMP_FAST_FILTER_MIN
||
370 value
> IWL_BF_TEMP_FAST_FILTER_MAX
)
372 param
= MVM_DEBUGFS_BF_TEMP_FAST_FILTER
;
373 } else if (!strncmp("bf_temp_slow_filter=", buf
, 20)) {
374 if (sscanf(buf
+20, "%d", &value
) != 1)
376 if (value
< IWL_BF_TEMP_SLOW_FILTER_MIN
||
377 value
> IWL_BF_TEMP_SLOW_FILTER_MAX
)
379 param
= MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
;
380 } else if (!strncmp("bf_enable_beacon_filter=", buf
, 24)) {
381 if (sscanf(buf
+24, "%d", &value
) != 1)
383 if (value
< 0 || value
> 1)
385 param
= MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
386 } else if (!strncmp("bf_debug_flag=", buf
, 14)) {
387 if (sscanf(buf
+14, "%d", &value
) != 1)
389 if (value
< 0 || value
> 1)
391 param
= MVM_DEBUGFS_BF_DEBUG_FLAG
;
392 } else if (!strncmp("bf_escape_timer=", buf
, 16)) {
393 if (sscanf(buf
+16, "%d", &value
) != 1)
395 if (value
< IWL_BF_ESCAPE_TIMER_MIN
||
396 value
> IWL_BF_ESCAPE_TIMER_MAX
)
398 param
= MVM_DEBUGFS_BF_ESCAPE_TIMER
;
399 } else if (!strncmp("ba_escape_timer=", buf
, 16)) {
400 if (sscanf(buf
+16, "%d", &value
) != 1)
402 if (value
< IWL_BA_ESCAPE_TIMER_MIN
||
403 value
> IWL_BA_ESCAPE_TIMER_MAX
)
405 param
= MVM_DEBUGFS_BA_ESCAPE_TIMER
;
406 } else if (!strncmp("ba_enable_beacon_abort=", buf
, 23)) {
407 if (sscanf(buf
+23, "%d", &value
) != 1)
409 if (value
< 0 || value
> 1)
411 param
= MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
416 mutex_lock(&mvm
->mutex
);
417 iwl_dbgfs_update_bf(vif
, param
, value
);
418 if (param
== MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&& !value
)
419 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
, 0);
421 ret
= iwl_mvm_enable_beacon_filter(mvm
, vif
, 0);
422 mutex_unlock(&mvm
->mutex
);
427 static ssize_t
iwl_dbgfs_bf_params_read(struct file
*file
,
428 char __user
*user_buf
,
429 size_t count
, loff_t
*ppos
)
431 struct ieee80211_vif
*vif
= file
->private_data
;
432 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
435 const size_t bufsz
= sizeof(buf
);
436 struct iwl_beacon_filter_cmd cmd
= {
437 IWL_BF_CMD_CONFIG_DEFAULTS
,
438 .bf_enable_beacon_filter
=
439 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
),
440 .ba_enable_beacon_abort
=
441 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
),
444 iwl_mvm_beacon_filter_debugfs_parameters(vif
, &cmd
);
445 if (mvmvif
->bf_data
.bf_enabled
)
446 cmd
.bf_enable_beacon_filter
= cpu_to_le32(1);
448 cmd
.bf_enable_beacon_filter
= 0;
450 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_energy_delta = %d\n",
451 le32_to_cpu(cmd
.bf_energy_delta
));
452 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_energy_delta = %d\n",
453 le32_to_cpu(cmd
.bf_roaming_energy_delta
));
454 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_state = %d\n",
455 le32_to_cpu(cmd
.bf_roaming_state
));
456 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_threshold = %d\n",
457 le32_to_cpu(cmd
.bf_temp_threshold
));
458 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_fast_filter = %d\n",
459 le32_to_cpu(cmd
.bf_temp_fast_filter
));
460 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_slow_filter = %d\n",
461 le32_to_cpu(cmd
.bf_temp_slow_filter
));
462 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_enable_beacon_filter = %d\n",
463 le32_to_cpu(cmd
.bf_enable_beacon_filter
));
464 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_debug_flag = %d\n",
465 le32_to_cpu(cmd
.bf_debug_flag
));
466 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_escape_timer = %d\n",
467 le32_to_cpu(cmd
.bf_escape_timer
));
468 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_escape_timer = %d\n",
469 le32_to_cpu(cmd
.ba_escape_timer
));
470 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_enable_beacon_abort = %d\n",
471 le32_to_cpu(cmd
.ba_enable_beacon_abort
));
473 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
476 static ssize_t
iwl_dbgfs_low_latency_write(struct ieee80211_vif
*vif
, char *buf
,
477 size_t count
, loff_t
*ppos
)
479 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
480 struct iwl_mvm
*mvm
= mvmvif
->mvm
;
484 ret
= kstrtou8(buf
, 0, &value
);
490 mutex_lock(&mvm
->mutex
);
491 iwl_mvm_update_low_latency(mvm
, vif
, value
);
492 mutex_unlock(&mvm
->mutex
);
497 static ssize_t
iwl_dbgfs_low_latency_read(struct file
*file
,
498 char __user
*user_buf
,
499 size_t count
, loff_t
*ppos
)
501 struct ieee80211_vif
*vif
= file
->private_data
;
502 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
505 buf
[0] = mvmvif
->low_latency
? '1' : '0';
508 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, sizeof(buf
));
511 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
512 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
513 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
514 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
515 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
516 if (!debugfs_create_file(#name, mode, parent, vif, \
517 &iwl_dbgfs_##name##_ops)) \
521 MVM_DEBUGFS_READ_FILE_OPS(mac_params
);
522 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params
, 32);
523 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params
, 256);
524 MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency
, 10);
526 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
528 struct dentry
*dbgfs_dir
= vif
->debugfs_dir
;
529 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
533 * Check if debugfs directory already exist before creating it.
534 * This may happen when, for example, resetting hw or suspend-resume
536 if (!dbgfs_dir
|| mvmvif
->dbgfs_dir
)
539 mvmvif
->dbgfs_dir
= debugfs_create_dir("iwlmvm", dbgfs_dir
);
542 if (!mvmvif
->dbgfs_dir
) {
543 IWL_ERR(mvm
, "Failed to create debugfs directory under %s\n",
544 dbgfs_dir
->d_name
.name
);
548 if (iwlmvm_mod_params
.power_scheme
!= IWL_POWER_SCHEME_CAM
&&
549 ((vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
) ||
550 (vif
->type
== NL80211_IFTYPE_STATION
&& vif
->p2p
&&
551 mvm
->fw
->ucode_capa
.flags
& IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM
)))
552 MVM_DEBUGFS_ADD_FILE_VIF(pm_params
, mvmvif
->dbgfs_dir
, S_IWUSR
|
555 MVM_DEBUGFS_ADD_FILE_VIF(mac_params
, mvmvif
->dbgfs_dir
, S_IRUSR
);
556 MVM_DEBUGFS_ADD_FILE_VIF(low_latency
, mvmvif
->dbgfs_dir
,
559 if (vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
560 mvmvif
== mvm
->bf_allowed_vif
)
561 MVM_DEBUGFS_ADD_FILE_VIF(bf_params
, mvmvif
->dbgfs_dir
,
565 * Create symlink for convenience pointing to interface specific
566 * debugfs entries for the driver. For example, under
567 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
569 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
571 snprintf(buf
, 100, "../../../%s/%s/%s/%s",
572 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
573 dbgfs_dir
->d_parent
->d_name
.name
,
574 dbgfs_dir
->d_name
.name
,
575 mvmvif
->dbgfs_dir
->d_name
.name
);
577 mvmvif
->dbgfs_slink
= debugfs_create_symlink(dbgfs_dir
->d_name
.name
,
578 mvm
->debugfs_dir
, buf
);
579 if (!mvmvif
->dbgfs_slink
)
580 IWL_ERR(mvm
, "Can't create debugfs symbolic link under %s\n",
581 dbgfs_dir
->d_name
.name
);
584 IWL_ERR(mvm
, "Can't create debugfs entity\n");
587 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
589 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
591 debugfs_remove(mvmvif
->dbgfs_slink
);
592 mvmvif
->dbgfs_slink
= NULL
;
594 debugfs_remove_recursive(mvmvif
->dbgfs_dir
);
595 mvmvif
->dbgfs_dir
= NULL
;