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 - 2013 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 - 2013 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 *****************************************************************************/
67 struct iwl_dbgfs_mvm_ctx
{
69 struct ieee80211_vif
*vif
;
72 static ssize_t
iwl_dbgfs_tx_flush_write(struct file
*file
,
73 const char __user
*user_buf
,
74 size_t count
, loff_t
*ppos
)
76 struct iwl_mvm
*mvm
= file
->private_data
;
82 if (!mvm
->ucode_loaded
|| mvm
->cur_ucode
!= IWL_UCODE_REGULAR
)
85 memset(buf
, 0, sizeof(buf
));
86 buf_size
= min(count
, sizeof(buf
) - 1);
87 if (copy_from_user(buf
, user_buf
, buf_size
))
90 if (sscanf(buf
, "%x", &scd_q_msk
) != 1)
93 IWL_ERR(mvm
, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk
);
95 mutex_lock(&mvm
->mutex
);
96 ret
= iwl_mvm_flush_tx_path(mvm
, scd_q_msk
, true) ? : count
;
97 mutex_unlock(&mvm
->mutex
);
102 static ssize_t
iwl_dbgfs_sta_drain_write(struct file
*file
,
103 const char __user
*user_buf
,
104 size_t count
, loff_t
*ppos
)
106 struct iwl_mvm
*mvm
= file
->private_data
;
107 struct ieee80211_sta
*sta
;
110 int buf_size
, sta_id
, drain
, ret
;
112 if (!mvm
->ucode_loaded
|| mvm
->cur_ucode
!= IWL_UCODE_REGULAR
)
115 memset(buf
, 0, sizeof(buf
));
116 buf_size
= min(count
, sizeof(buf
) - 1);
117 if (copy_from_user(buf
, user_buf
, buf_size
))
120 if (sscanf(buf
, "%d %d", &sta_id
, &drain
) != 2)
123 mutex_lock(&mvm
->mutex
);
125 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[sta_id
],
126 lockdep_is_held(&mvm
->mutex
));
127 if (IS_ERR_OR_NULL(sta
))
130 ret
= iwl_mvm_drain_sta(mvm
, (void *)sta
->drv_priv
, drain
) ? :
133 mutex_unlock(&mvm
->mutex
);
138 static ssize_t
iwl_dbgfs_sram_read(struct file
*file
, char __user
*user_buf
,
139 size_t count
, loff_t
*ppos
)
141 struct iwl_mvm
*mvm
= file
->private_data
;
142 const struct fw_img
*img
;
143 int ofs
, len
, pos
= 0;
148 if (!mvm
->ucode_loaded
)
151 /* default is to dump the entire data segment */
152 if (!mvm
->dbgfs_sram_offset
&& !mvm
->dbgfs_sram_len
) {
153 img
= &mvm
->fw
->img
[mvm
->cur_ucode
];
154 ofs
= img
->sec
[IWL_UCODE_SECTION_DATA
].offset
;
155 len
= img
->sec
[IWL_UCODE_SECTION_DATA
].len
;
157 ofs
= mvm
->dbgfs_sram_offset
;
158 len
= mvm
->dbgfs_sram_len
;
161 bufsz
= len
* 4 + 256;
162 buf
= kzalloc(bufsz
, GFP_KERNEL
);
166 ptr
= kzalloc(len
, GFP_KERNEL
);
172 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "sram_len: 0x%x\n", len
);
173 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "sram_offset: 0x%x\n", ofs
);
175 iwl_trans_read_mem_bytes(mvm
->trans
, ofs
, ptr
, len
);
176 for (ofs
= 0; ofs
< len
; ofs
+= 16) {
177 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "0x%.4x ", ofs
);
178 hex_dump_to_buffer(ptr
+ ofs
, 16, 16, 1, buf
+ pos
,
180 pos
+= strlen(buf
+ pos
);
185 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
193 static ssize_t
iwl_dbgfs_sram_write(struct file
*file
,
194 const char __user
*user_buf
, size_t count
,
197 struct iwl_mvm
*mvm
= file
->private_data
;
202 memset(buf
, 0, sizeof(buf
));
203 buf_size
= min(count
, sizeof(buf
) - 1);
204 if (copy_from_user(buf
, user_buf
, buf_size
))
207 if (sscanf(buf
, "%x,%x", &offset
, &len
) == 2) {
208 if ((offset
& 0x3) || (len
& 0x3))
210 mvm
->dbgfs_sram_offset
= offset
;
211 mvm
->dbgfs_sram_len
= len
;
213 mvm
->dbgfs_sram_offset
= 0;
214 mvm
->dbgfs_sram_len
= 0;
220 static ssize_t
iwl_dbgfs_stations_read(struct file
*file
, char __user
*user_buf
,
221 size_t count
, loff_t
*ppos
)
223 struct iwl_mvm
*mvm
= file
->private_data
;
224 struct ieee80211_sta
*sta
;
226 int i
, pos
= 0, bufsz
= sizeof(buf
);
228 mutex_lock(&mvm
->mutex
);
230 for (i
= 0; i
< IWL_MVM_STATION_COUNT
; i
++) {
231 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "%.2d: ", i
);
232 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[i
],
233 lockdep_is_held(&mvm
->mutex
));
235 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "N/A\n");
236 else if (IS_ERR(sta
))
237 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "%ld\n",
240 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "%pM\n",
244 mutex_unlock(&mvm
->mutex
);
246 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
249 static ssize_t
iwl_dbgfs_disable_power_off_read(struct file
*file
,
250 char __user
*user_buf
,
251 size_t count
, loff_t
*ppos
)
253 struct iwl_mvm
*mvm
= file
->private_data
;
255 int bufsz
= sizeof(buf
);
258 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "disable_power_off_d0=%d\n",
259 mvm
->disable_power_off
);
260 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "disable_power_off_d3=%d\n",
261 mvm
->disable_power_off_d3
);
263 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
266 static ssize_t
iwl_dbgfs_disable_power_off_write(struct file
*file
,
267 const char __user
*user_buf
,
268 size_t count
, loff_t
*ppos
)
270 struct iwl_mvm
*mvm
= file
->private_data
;
275 if (!mvm
->ucode_loaded
)
278 count
= min_t(size_t, count
, sizeof(buf
) - 1);
279 if (copy_from_user(buf
, user_buf
, count
))
282 if (!strncmp("disable_power_off_d0=", buf
, 21)) {
283 if (sscanf(buf
+ 21, "%d", &val
) != 1)
285 mvm
->disable_power_off
= val
;
286 } else if (!strncmp("disable_power_off_d3=", buf
, 21)) {
287 if (sscanf(buf
+ 21, "%d", &val
) != 1)
289 mvm
->disable_power_off_d3
= val
;
294 mutex_lock(&mvm
->mutex
);
295 ret
= iwl_mvm_power_update_device_mode(mvm
);
296 mutex_unlock(&mvm
->mutex
);
301 static void iwl_dbgfs_update_pm(struct iwl_mvm
*mvm
,
302 struct ieee80211_vif
*vif
,
303 enum iwl_dbgfs_pm_mask param
, int val
)
305 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
306 struct iwl_dbgfs_pm
*dbgfs_pm
= &mvmvif
->dbgfs_pm
;
308 dbgfs_pm
->mask
|= param
;
311 case MVM_DEBUGFS_PM_KEEP_ALIVE
: {
312 struct ieee80211_hw
*hw
= mvm
->hw
;
313 int dtimper
= hw
->conf
.ps_dtim_period
?: 1;
314 int dtimper_msec
= dtimper
* vif
->bss_conf
.beacon_int
;
316 IWL_DEBUG_POWER(mvm
, "debugfs: set keep_alive= %d sec\n", val
);
317 if (val
* MSEC_PER_SEC
< 3 * dtimper_msec
) {
319 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
320 val
* MSEC_PER_SEC
, 3 * dtimper_msec
);
322 dbgfs_pm
->keep_alive_seconds
= val
;
325 case MVM_DEBUGFS_PM_SKIP_OVER_DTIM
:
326 IWL_DEBUG_POWER(mvm
, "skip_over_dtim %s\n",
327 val
? "enabled" : "disabled");
328 dbgfs_pm
->skip_over_dtim
= val
;
330 case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
:
331 IWL_DEBUG_POWER(mvm
, "skip_dtim_periods=%d\n", val
);
332 dbgfs_pm
->skip_dtim_periods
= val
;
334 case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
:
335 IWL_DEBUG_POWER(mvm
, "rx_data_timeout=%d\n", val
);
336 dbgfs_pm
->rx_data_timeout
= val
;
338 case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
:
339 IWL_DEBUG_POWER(mvm
, "tx_data_timeout=%d\n", val
);
340 dbgfs_pm
->tx_data_timeout
= val
;
342 case MVM_DEBUGFS_PM_DISABLE_POWER_OFF
:
343 IWL_DEBUG_POWER(mvm
, "disable_power_off=%d\n", val
);
344 dbgfs_pm
->disable_power_off
= val
;
345 case MVM_DEBUGFS_PM_LPRX_ENA
:
346 IWL_DEBUG_POWER(mvm
, "lprx %s\n", val
? "enabled" : "disabled");
347 dbgfs_pm
->lprx_ena
= val
;
349 case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
:
350 IWL_DEBUG_POWER(mvm
, "lprx_rssi_threshold=%d\n", val
);
351 dbgfs_pm
->lprx_rssi_threshold
= val
;
353 case MVM_DEBUGFS_PM_SNOOZE_ENABLE
:
354 IWL_DEBUG_POWER(mvm
, "snooze_enable=%d\n", val
);
355 dbgfs_pm
->snooze_ena
= val
;
360 static ssize_t
iwl_dbgfs_pm_params_write(struct file
*file
,
361 const char __user
*user_buf
,
362 size_t count
, loff_t
*ppos
)
364 struct ieee80211_vif
*vif
= file
->private_data
;
365 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
366 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
367 enum iwl_dbgfs_pm_mask param
;
372 count
= min_t(size_t, count
, sizeof(buf
) - 1);
373 if (copy_from_user(buf
, user_buf
, count
))
376 if (!strncmp("keep_alive=", buf
, 11)) {
377 if (sscanf(buf
+ 11, "%d", &val
) != 1)
379 param
= MVM_DEBUGFS_PM_KEEP_ALIVE
;
380 } else if (!strncmp("skip_over_dtim=", buf
, 15)) {
381 if (sscanf(buf
+ 15, "%d", &val
) != 1)
383 param
= MVM_DEBUGFS_PM_SKIP_OVER_DTIM
;
384 } else if (!strncmp("skip_dtim_periods=", buf
, 18)) {
385 if (sscanf(buf
+ 18, "%d", &val
) != 1)
387 param
= MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS
;
388 } else if (!strncmp("rx_data_timeout=", buf
, 16)) {
389 if (sscanf(buf
+ 16, "%d", &val
) != 1)
391 param
= MVM_DEBUGFS_PM_RX_DATA_TIMEOUT
;
392 } else if (!strncmp("tx_data_timeout=", buf
, 16)) {
393 if (sscanf(buf
+ 16, "%d", &val
) != 1)
395 param
= MVM_DEBUGFS_PM_TX_DATA_TIMEOUT
;
396 } else if (!strncmp("disable_power_off=", buf
, 18) &&
397 !(mvm
->fw
->ucode_capa
.flags
&
398 IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD
)) {
399 if (sscanf(buf
+ 18, "%d", &val
) != 1)
401 param
= MVM_DEBUGFS_PM_DISABLE_POWER_OFF
;
402 } else if (!strncmp("lprx=", buf
, 5)) {
403 if (sscanf(buf
+ 5, "%d", &val
) != 1)
405 param
= MVM_DEBUGFS_PM_LPRX_ENA
;
406 } else if (!strncmp("lprx_rssi_threshold=", buf
, 20)) {
407 if (sscanf(buf
+ 20, "%d", &val
) != 1)
409 if (val
> POWER_LPRX_RSSI_THRESHOLD_MAX
|| val
<
410 POWER_LPRX_RSSI_THRESHOLD_MIN
)
412 param
= MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD
;
413 } else if (!strncmp("snooze_enable=", buf
, 14)) {
414 if (sscanf(buf
+ 14, "%d", &val
) != 1)
416 param
= MVM_DEBUGFS_PM_SNOOZE_ENABLE
;
421 mutex_lock(&mvm
->mutex
);
422 iwl_dbgfs_update_pm(mvm
, vif
, param
, val
);
423 ret
= iwl_mvm_power_update_mode(mvm
, vif
);
424 mutex_unlock(&mvm
->mutex
);
429 static ssize_t
iwl_dbgfs_pm_params_read(struct file
*file
,
430 char __user
*user_buf
,
431 size_t count
, loff_t
*ppos
)
433 struct ieee80211_vif
*vif
= file
->private_data
;
434 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
435 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
437 int bufsz
= sizeof(buf
);
440 pos
= iwl_mvm_power_dbgfs_read(mvm
, vif
, buf
, bufsz
);
442 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
445 static ssize_t
iwl_dbgfs_mac_params_read(struct file
*file
,
446 char __user
*user_buf
,
447 size_t count
, loff_t
*ppos
)
449 struct ieee80211_vif
*vif
= file
->private_data
;
450 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
451 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
453 struct ieee80211_chanctx_conf
*chanctx_conf
;
455 int bufsz
= sizeof(buf
);
459 mutex_lock(&mvm
->mutex
);
461 ap_sta_id
= mvmvif
->ap_sta_id
;
463 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "mac id/color: %d / %d\n",
464 mvmvif
->id
, mvmvif
->color
);
465 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bssid: %pM\n",
466 vif
->bss_conf
.bssid
);
467 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "QoS:\n");
468 for (i
= 0; i
< ARRAY_SIZE(mvmvif
->queue_params
); i
++) {
469 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
470 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
471 i
, mvmvif
->queue_params
[i
].txop
,
472 mvmvif
->queue_params
[i
].cw_min
,
473 mvmvif
->queue_params
[i
].cw_max
,
474 mvmvif
->queue_params
[i
].aifs
,
475 mvmvif
->queue_params
[i
].uapsd
);
478 if (vif
->type
== NL80211_IFTYPE_STATION
&&
479 ap_sta_id
!= IWL_MVM_STATION_COUNT
) {
480 struct ieee80211_sta
*sta
;
481 struct iwl_mvm_sta
*mvm_sta
;
483 sta
= rcu_dereference_protected(mvm
->fw_id_to_mac_id
[ap_sta_id
],
484 lockdep_is_held(&mvm
->mutex
));
485 mvm_sta
= (void *)sta
->drv_priv
;
486 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
487 "ap_sta_id %d - reduced Tx power %d\n",
488 ap_sta_id
, mvm_sta
->bt_reduced_txpower
);
492 chanctx_conf
= rcu_dereference(vif
->chanctx_conf
);
494 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
495 "idle rx chains %d, active rx chains: %d\n",
496 chanctx_conf
->rx_chains_static
,
497 chanctx_conf
->rx_chains_dynamic
);
501 mutex_unlock(&mvm
->mutex
);
503 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
506 #define BT_MBOX_MSG(_notif, _num, _field) \
507 ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
508 >> BT_MBOX##_num##_##_field##_POS)
511 #define BT_MBOX_PRINT(_num, _field, _end) \
512 pos += scnprintf(buf + pos, bufsz - pos, \
515 BT_MBOX_MSG(notif, _num, _field), \
518 static ssize_t
iwl_dbgfs_bt_notif_read(struct file
*file
, char __user
*user_buf
,
519 size_t count
, loff_t
*ppos
)
521 struct iwl_mvm
*mvm
= file
->private_data
;
522 struct iwl_bt_coex_profile_notif
*notif
= &mvm
->last_bt_notif
;
524 int ret
, pos
= 0, bufsz
= sizeof(char) * 1024;
526 buf
= kmalloc(bufsz
, GFP_KERNEL
);
530 mutex_lock(&mvm
->mutex
);
532 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw0:\n");
534 BT_MBOX_PRINT(0, LE_SLAVE_LAT
, false);
535 BT_MBOX_PRINT(0, LE_PROF1
, false);
536 BT_MBOX_PRINT(0, LE_PROF2
, false);
537 BT_MBOX_PRINT(0, LE_PROF_OTHER
, false);
538 BT_MBOX_PRINT(0, CHL_SEQ_N
, false);
539 BT_MBOX_PRINT(0, INBAND_S
, false);
540 BT_MBOX_PRINT(0, LE_MIN_RSSI
, false);
541 BT_MBOX_PRINT(0, LE_SCAN
, false);
542 BT_MBOX_PRINT(0, LE_ADV
, false);
543 BT_MBOX_PRINT(0, LE_MAX_TX_POWER
, false);
544 BT_MBOX_PRINT(0, OPEN_CON_1
, true);
546 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw1:\n");
548 BT_MBOX_PRINT(1, BR_MAX_TX_POWER
, false);
549 BT_MBOX_PRINT(1, IP_SR
, false);
550 BT_MBOX_PRINT(1, LE_MSTR
, false);
551 BT_MBOX_PRINT(1, AGGR_TRFC_LD
, false);
552 BT_MBOX_PRINT(1, MSG_TYPE
, false);
553 BT_MBOX_PRINT(1, SSN
, true);
555 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw2:\n");
557 BT_MBOX_PRINT(2, SNIFF_ACT
, false);
558 BT_MBOX_PRINT(2, PAG
, false);
559 BT_MBOX_PRINT(2, INQUIRY
, false);
560 BT_MBOX_PRINT(2, CONN
, false);
561 BT_MBOX_PRINT(2, SNIFF_INTERVAL
, false);
562 BT_MBOX_PRINT(2, DISC
, false);
563 BT_MBOX_PRINT(2, SCO_TX_ACT
, false);
564 BT_MBOX_PRINT(2, SCO_RX_ACT
, false);
565 BT_MBOX_PRINT(2, ESCO_RE_TX
, false);
566 BT_MBOX_PRINT(2, SCO_DURATION
, true);
568 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "MBOX dw3:\n");
570 BT_MBOX_PRINT(3, SCO_STATE
, false);
571 BT_MBOX_PRINT(3, SNIFF_STATE
, false);
572 BT_MBOX_PRINT(3, A2DP_STATE
, false);
573 BT_MBOX_PRINT(3, ACL_STATE
, false);
574 BT_MBOX_PRINT(3, MSTR_STATE
, false);
575 BT_MBOX_PRINT(3, OBX_STATE
, false);
576 BT_MBOX_PRINT(3, OPEN_CON_2
, false);
577 BT_MBOX_PRINT(3, TRAFFIC_LOAD
, false);
578 BT_MBOX_PRINT(3, CHL_SEQN_LSB
, false);
579 BT_MBOX_PRINT(3, INBAND_P
, false);
580 BT_MBOX_PRINT(3, MSG_TYPE_2
, false);
581 BT_MBOX_PRINT(3, SSN_2
, false);
582 BT_MBOX_PRINT(3, UPDATE_REQUEST
, true);
584 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_status = %d\n",
586 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_open_conn = %d\n",
587 notif
->bt_open_conn
);
588 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_traffic_load = %d\n",
589 notif
->bt_traffic_load
);
590 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_agg_traffic_load = %d\n",
591 notif
->bt_agg_traffic_load
);
592 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_ci_compliance = %d\n",
593 notif
->bt_ci_compliance
);
594 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "primary_ch_lut = %d\n",
595 le32_to_cpu(notif
->primary_ch_lut
));
596 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "secondary_ch_lut = %d\n",
597 le32_to_cpu(notif
->secondary_ch_lut
));
598 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bt_activity_grading = %d\n",
599 le32_to_cpu(notif
->bt_activity_grading
));
601 mutex_unlock(&mvm
->mutex
);
603 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
610 static ssize_t
iwl_dbgfs_bt_cmd_read(struct file
*file
, char __user
*user_buf
,
611 size_t count
, loff_t
*ppos
)
613 struct iwl_mvm
*mvm
= file
->private_data
;
614 struct iwl_bt_coex_ci_cmd
*cmd
= &mvm
->last_bt_ci_cmd
;
616 int bufsz
= sizeof(buf
);
619 mutex_lock(&mvm
->mutex
);
621 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "Channel inhibition CMD\n");
622 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
623 "\tPrimary Channel Bitmap 0x%016llx Fat: %d\n",
624 le64_to_cpu(cmd
->bt_primary_ci
),
625 !!cmd
->co_run_bw_primary
);
626 pos
+= scnprintf(buf
+pos
, bufsz
-pos
,
627 "\tSecondary Channel Bitmap 0x%016llx Fat: %d\n",
628 le64_to_cpu(cmd
->bt_secondary_ci
),
629 !!cmd
->co_run_bw_secondary
);
631 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "BT Configuration CMD\n");
632 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "\tACK Kill Mask 0x%08x\n",
633 iwl_bt_ack_kill_msk
[mvm
->bt_kill_msk
]);
634 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "\tCTS Kill Mask 0x%08x\n",
635 iwl_bt_cts_kill_msk
[mvm
->bt_kill_msk
]);
637 mutex_unlock(&mvm
->mutex
);
639 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
642 #define PRINT_STATS_LE32(_str, _val) \
643 pos += scnprintf(buf + pos, bufsz - pos, \
647 static ssize_t
iwl_dbgfs_fw_rx_stats_read(struct file
*file
,
648 char __user
*user_buf
, size_t count
,
651 struct iwl_mvm
*mvm
= file
->private_data
;
652 static const char *fmt_table
= "\t%-30s %10u\n";
653 static const char *fmt_header
= "%-32s\n";
657 int bufsz
= sizeof(struct mvm_statistics_rx_phy
) * 20 +
658 sizeof(struct mvm_statistics_rx_non_phy
) * 10 +
659 sizeof(struct mvm_statistics_rx_ht_phy
) * 10 + 200;
660 struct mvm_statistics_rx_phy
*ofdm
;
661 struct mvm_statistics_rx_phy
*cck
;
662 struct mvm_statistics_rx_non_phy
*general
;
663 struct mvm_statistics_rx_ht_phy
*ht
;
665 buf
= kzalloc(bufsz
, GFP_KERNEL
);
669 mutex_lock(&mvm
->mutex
);
671 ofdm
= &mvm
->rx_stats
.ofdm
;
672 cck
= &mvm
->rx_stats
.cck
;
673 general
= &mvm
->rx_stats
.general
;
674 ht
= &mvm
->rx_stats
.ofdm_ht
;
676 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, fmt_header
,
677 "Statistics_Rx - OFDM");
678 PRINT_STATS_LE32("ina_cnt", ofdm
->ina_cnt
);
679 PRINT_STATS_LE32("fina_cnt", ofdm
->fina_cnt
);
680 PRINT_STATS_LE32("plcp_err", ofdm
->plcp_err
);
681 PRINT_STATS_LE32("crc32_err", ofdm
->crc32_err
);
682 PRINT_STATS_LE32("overrun_err", ofdm
->overrun_err
);
683 PRINT_STATS_LE32("early_overrun_err", ofdm
->early_overrun_err
);
684 PRINT_STATS_LE32("crc32_good", ofdm
->crc32_good
);
685 PRINT_STATS_LE32("false_alarm_cnt", ofdm
->false_alarm_cnt
);
686 PRINT_STATS_LE32("fina_sync_err_cnt", ofdm
->fina_sync_err_cnt
);
687 PRINT_STATS_LE32("sfd_timeout", ofdm
->sfd_timeout
);
688 PRINT_STATS_LE32("fina_timeout", ofdm
->fina_timeout
);
689 PRINT_STATS_LE32("unresponded_rts", ofdm
->unresponded_rts
);
690 PRINT_STATS_LE32("rxe_frame_lmt_overrun",
691 ofdm
->rxe_frame_limit_overrun
);
692 PRINT_STATS_LE32("sent_ack_cnt", ofdm
->sent_ack_cnt
);
693 PRINT_STATS_LE32("sent_cts_cnt", ofdm
->sent_cts_cnt
);
694 PRINT_STATS_LE32("sent_ba_rsp_cnt", ofdm
->sent_ba_rsp_cnt
);
695 PRINT_STATS_LE32("dsp_self_kill", ofdm
->dsp_self_kill
);
696 PRINT_STATS_LE32("mh_format_err", ofdm
->mh_format_err
);
697 PRINT_STATS_LE32("re_acq_main_rssi_sum", ofdm
->re_acq_main_rssi_sum
);
698 PRINT_STATS_LE32("reserved", ofdm
->reserved
);
700 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, fmt_header
,
701 "Statistics_Rx - CCK");
702 PRINT_STATS_LE32("ina_cnt", cck
->ina_cnt
);
703 PRINT_STATS_LE32("fina_cnt", cck
->fina_cnt
);
704 PRINT_STATS_LE32("plcp_err", cck
->plcp_err
);
705 PRINT_STATS_LE32("crc32_err", cck
->crc32_err
);
706 PRINT_STATS_LE32("overrun_err", cck
->overrun_err
);
707 PRINT_STATS_LE32("early_overrun_err", cck
->early_overrun_err
);
708 PRINT_STATS_LE32("crc32_good", cck
->crc32_good
);
709 PRINT_STATS_LE32("false_alarm_cnt", cck
->false_alarm_cnt
);
710 PRINT_STATS_LE32("fina_sync_err_cnt", cck
->fina_sync_err_cnt
);
711 PRINT_STATS_LE32("sfd_timeout", cck
->sfd_timeout
);
712 PRINT_STATS_LE32("fina_timeout", cck
->fina_timeout
);
713 PRINT_STATS_LE32("unresponded_rts", cck
->unresponded_rts
);
714 PRINT_STATS_LE32("rxe_frame_lmt_overrun",
715 cck
->rxe_frame_limit_overrun
);
716 PRINT_STATS_LE32("sent_ack_cnt", cck
->sent_ack_cnt
);
717 PRINT_STATS_LE32("sent_cts_cnt", cck
->sent_cts_cnt
);
718 PRINT_STATS_LE32("sent_ba_rsp_cnt", cck
->sent_ba_rsp_cnt
);
719 PRINT_STATS_LE32("dsp_self_kill", cck
->dsp_self_kill
);
720 PRINT_STATS_LE32("mh_format_err", cck
->mh_format_err
);
721 PRINT_STATS_LE32("re_acq_main_rssi_sum", cck
->re_acq_main_rssi_sum
);
722 PRINT_STATS_LE32("reserved", cck
->reserved
);
724 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, fmt_header
,
725 "Statistics_Rx - GENERAL");
726 PRINT_STATS_LE32("bogus_cts", general
->bogus_cts
);
727 PRINT_STATS_LE32("bogus_ack", general
->bogus_ack
);
728 PRINT_STATS_LE32("non_bssid_frames", general
->non_bssid_frames
);
729 PRINT_STATS_LE32("filtered_frames", general
->filtered_frames
);
730 PRINT_STATS_LE32("non_channel_beacons", general
->non_channel_beacons
);
731 PRINT_STATS_LE32("channel_beacons", general
->channel_beacons
);
732 PRINT_STATS_LE32("num_missed_bcon", general
->num_missed_bcon
);
733 PRINT_STATS_LE32("adc_rx_saturation_time",
734 general
->adc_rx_saturation_time
);
735 PRINT_STATS_LE32("ina_detection_search_time",
736 general
->ina_detection_search_time
);
737 PRINT_STATS_LE32("beacon_silence_rssi_a",
738 general
->beacon_silence_rssi_a
);
739 PRINT_STATS_LE32("beacon_silence_rssi_b",
740 general
->beacon_silence_rssi_b
);
741 PRINT_STATS_LE32("beacon_silence_rssi_c",
742 general
->beacon_silence_rssi_c
);
743 PRINT_STATS_LE32("interference_data_flag",
744 general
->interference_data_flag
);
745 PRINT_STATS_LE32("channel_load", general
->channel_load
);
746 PRINT_STATS_LE32("dsp_false_alarms", general
->dsp_false_alarms
);
747 PRINT_STATS_LE32("beacon_rssi_a", general
->beacon_rssi_a
);
748 PRINT_STATS_LE32("beacon_rssi_b", general
->beacon_rssi_b
);
749 PRINT_STATS_LE32("beacon_rssi_c", general
->beacon_rssi_c
);
750 PRINT_STATS_LE32("beacon_energy_a", general
->beacon_energy_a
);
751 PRINT_STATS_LE32("beacon_energy_b", general
->beacon_energy_b
);
752 PRINT_STATS_LE32("beacon_energy_c", general
->beacon_energy_c
);
753 PRINT_STATS_LE32("num_bt_kills", general
->num_bt_kills
);
754 PRINT_STATS_LE32("directed_data_mpdu", general
->directed_data_mpdu
);
756 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, fmt_header
,
757 "Statistics_Rx - HT");
758 PRINT_STATS_LE32("plcp_err", ht
->plcp_err
);
759 PRINT_STATS_LE32("overrun_err", ht
->overrun_err
);
760 PRINT_STATS_LE32("early_overrun_err", ht
->early_overrun_err
);
761 PRINT_STATS_LE32("crc32_good", ht
->crc32_good
);
762 PRINT_STATS_LE32("crc32_err", ht
->crc32_err
);
763 PRINT_STATS_LE32("mh_format_err", ht
->mh_format_err
);
764 PRINT_STATS_LE32("agg_crc32_good", ht
->agg_crc32_good
);
765 PRINT_STATS_LE32("agg_mpdu_cnt", ht
->agg_mpdu_cnt
);
766 PRINT_STATS_LE32("agg_cnt", ht
->agg_cnt
);
767 PRINT_STATS_LE32("unsupport_mcs", ht
->unsupport_mcs
);
769 mutex_unlock(&mvm
->mutex
);
771 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
776 #undef PRINT_STAT_LE32
778 static ssize_t
iwl_dbgfs_fw_restart_write(struct file
*file
,
779 const char __user
*user_buf
,
780 size_t count
, loff_t
*ppos
)
782 struct iwl_mvm
*mvm
= file
->private_data
;
785 mutex_lock(&mvm
->mutex
);
787 /* allow one more restart that we're provoking here */
788 if (mvm
->restart_fw
>= 0)
791 /* take the return value to make compiler happy - it will fail anyway */
792 ret
= iwl_mvm_send_cmd_pdu(mvm
, REPLY_ERROR
, CMD_SYNC
, 0, NULL
);
794 mutex_unlock(&mvm
->mutex
);
800 iwl_dbgfs_scan_ant_rxchain_read(struct file
*file
,
801 char __user
*user_buf
,
802 size_t count
, loff_t
*ppos
)
804 struct iwl_mvm
*mvm
= file
->private_data
;
807 const size_t bufsz
= sizeof(buf
);
809 /* print which antennas were set for the scan command by the user */
810 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "Antennas for scan: ");
811 if (mvm
->scan_rx_ant
& ANT_A
)
812 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "A");
813 if (mvm
->scan_rx_ant
& ANT_B
)
814 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "B");
815 if (mvm
->scan_rx_ant
& ANT_C
)
816 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, "C");
817 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
, " (%hhx)\n", mvm
->scan_rx_ant
);
819 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
823 iwl_dbgfs_scan_ant_rxchain_write(struct file
*file
,
824 const char __user
*user_buf
,
825 size_t count
, loff_t
*ppos
)
827 struct iwl_mvm
*mvm
= file
->private_data
;
832 memset(buf
, 0, sizeof(buf
));
833 buf_size
= min(count
, sizeof(buf
) - 1);
835 /* get the argument from the user and check if it is valid */
836 if (copy_from_user(buf
, user_buf
, buf_size
))
838 if (sscanf(buf
, "%hhx", &scan_rx_ant
) != 1)
840 if (scan_rx_ant
> ANT_ABC
)
842 if (scan_rx_ant
& ~iwl_fw_valid_rx_ant(mvm
->fw
))
845 /* change the rx antennas for scan command */
846 mvm
->scan_rx_ant
= scan_rx_ant
;
852 static void iwl_dbgfs_update_bf(struct ieee80211_vif
*vif
,
853 enum iwl_dbgfs_bf_mask param
, int value
)
855 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
856 struct iwl_dbgfs_bf
*dbgfs_bf
= &mvmvif
->dbgfs_bf
;
858 dbgfs_bf
->mask
|= param
;
861 case MVM_DEBUGFS_BF_ENERGY_DELTA
:
862 dbgfs_bf
->bf_energy_delta
= value
;
864 case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
:
865 dbgfs_bf
->bf_roaming_energy_delta
= value
;
867 case MVM_DEBUGFS_BF_ROAMING_STATE
:
868 dbgfs_bf
->bf_roaming_state
= value
;
870 case MVM_DEBUGFS_BF_TEMP_THRESHOLD
:
871 dbgfs_bf
->bf_temp_threshold
= value
;
873 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER
:
874 dbgfs_bf
->bf_temp_fast_filter
= value
;
876 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
:
877 dbgfs_bf
->bf_temp_slow_filter
= value
;
879 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
:
880 dbgfs_bf
->bf_enable_beacon_filter
= value
;
882 case MVM_DEBUGFS_BF_DEBUG_FLAG
:
883 dbgfs_bf
->bf_debug_flag
= value
;
885 case MVM_DEBUGFS_BF_ESCAPE_TIMER
:
886 dbgfs_bf
->bf_escape_timer
= value
;
888 case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
:
889 dbgfs_bf
->ba_enable_beacon_abort
= value
;
891 case MVM_DEBUGFS_BA_ESCAPE_TIMER
:
892 dbgfs_bf
->ba_escape_timer
= value
;
897 static ssize_t
iwl_dbgfs_bf_params_write(struct file
*file
,
898 const char __user
*user_buf
,
899 size_t count
, loff_t
*ppos
)
901 struct ieee80211_vif
*vif
= file
->private_data
;
902 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
903 struct iwl_mvm
*mvm
= mvmvif
->dbgfs_data
;
904 enum iwl_dbgfs_bf_mask param
;
910 memset(buf
, 0, sizeof(buf
));
911 buf_size
= min(count
, sizeof(buf
) - 1);
912 if (copy_from_user(buf
, user_buf
, buf_size
))
915 if (!strncmp("bf_energy_delta=", buf
, 16)) {
916 if (sscanf(buf
+16, "%d", &value
) != 1)
918 if (value
< IWL_BF_ENERGY_DELTA_MIN
||
919 value
> IWL_BF_ENERGY_DELTA_MAX
)
921 param
= MVM_DEBUGFS_BF_ENERGY_DELTA
;
922 } else if (!strncmp("bf_roaming_energy_delta=", buf
, 24)) {
923 if (sscanf(buf
+24, "%d", &value
) != 1)
925 if (value
< IWL_BF_ROAMING_ENERGY_DELTA_MIN
||
926 value
> IWL_BF_ROAMING_ENERGY_DELTA_MAX
)
928 param
= MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA
;
929 } else if (!strncmp("bf_roaming_state=", buf
, 17)) {
930 if (sscanf(buf
+17, "%d", &value
) != 1)
932 if (value
< IWL_BF_ROAMING_STATE_MIN
||
933 value
> IWL_BF_ROAMING_STATE_MAX
)
935 param
= MVM_DEBUGFS_BF_ROAMING_STATE
;
936 } else if (!strncmp("bf_temp_threshold=", buf
, 18)) {
937 if (sscanf(buf
+18, "%d", &value
) != 1)
939 if (value
< IWL_BF_TEMP_THRESHOLD_MIN
||
940 value
> IWL_BF_TEMP_THRESHOLD_MAX
)
942 param
= MVM_DEBUGFS_BF_TEMP_THRESHOLD
;
943 } else if (!strncmp("bf_temp_fast_filter=", buf
, 20)) {
944 if (sscanf(buf
+20, "%d", &value
) != 1)
946 if (value
< IWL_BF_TEMP_FAST_FILTER_MIN
||
947 value
> IWL_BF_TEMP_FAST_FILTER_MAX
)
949 param
= MVM_DEBUGFS_BF_TEMP_FAST_FILTER
;
950 } else if (!strncmp("bf_temp_slow_filter=", buf
, 20)) {
951 if (sscanf(buf
+20, "%d", &value
) != 1)
953 if (value
< IWL_BF_TEMP_SLOW_FILTER_MIN
||
954 value
> IWL_BF_TEMP_SLOW_FILTER_MAX
)
956 param
= MVM_DEBUGFS_BF_TEMP_SLOW_FILTER
;
957 } else if (!strncmp("bf_enable_beacon_filter=", buf
, 24)) {
958 if (sscanf(buf
+24, "%d", &value
) != 1)
960 if (value
< 0 || value
> 1)
962 param
= MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
;
963 } else if (!strncmp("bf_debug_flag=", buf
, 14)) {
964 if (sscanf(buf
+14, "%d", &value
) != 1)
966 if (value
< 0 || value
> 1)
968 param
= MVM_DEBUGFS_BF_DEBUG_FLAG
;
969 } else if (!strncmp("bf_escape_timer=", buf
, 16)) {
970 if (sscanf(buf
+16, "%d", &value
) != 1)
972 if (value
< IWL_BF_ESCAPE_TIMER_MIN
||
973 value
> IWL_BF_ESCAPE_TIMER_MAX
)
975 param
= MVM_DEBUGFS_BF_ESCAPE_TIMER
;
976 } else if (!strncmp("ba_escape_timer=", buf
, 16)) {
977 if (sscanf(buf
+16, "%d", &value
) != 1)
979 if (value
< IWL_BA_ESCAPE_TIMER_MIN
||
980 value
> IWL_BA_ESCAPE_TIMER_MAX
)
982 param
= MVM_DEBUGFS_BA_ESCAPE_TIMER
;
983 } else if (!strncmp("ba_enable_beacon_abort=", buf
, 23)) {
984 if (sscanf(buf
+23, "%d", &value
) != 1)
986 if (value
< 0 || value
> 1)
988 param
= MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT
;
993 mutex_lock(&mvm
->mutex
);
994 iwl_dbgfs_update_bf(vif
, param
, value
);
995 if (param
== MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER
&& !value
) {
996 ret
= iwl_mvm_disable_beacon_filter(mvm
, vif
);
998 ret
= iwl_mvm_enable_beacon_filter(mvm
, vif
);
1000 mutex_unlock(&mvm
->mutex
);
1002 return ret
?: count
;
1005 static ssize_t
iwl_dbgfs_bf_params_read(struct file
*file
,
1006 char __user
*user_buf
,
1007 size_t count
, loff_t
*ppos
)
1009 struct ieee80211_vif
*vif
= file
->private_data
;
1010 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1013 const size_t bufsz
= sizeof(buf
);
1014 struct iwl_beacon_filter_cmd cmd
= {
1015 IWL_BF_CMD_CONFIG_DEFAULTS
,
1016 .bf_enable_beacon_filter
=
1017 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT
),
1018 .ba_enable_beacon_abort
=
1019 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT
),
1022 iwl_mvm_beacon_filter_debugfs_parameters(vif
, &cmd
);
1023 if (mvmvif
->bf_data
.bf_enabled
)
1024 cmd
.bf_enable_beacon_filter
= cpu_to_le32(1);
1026 cmd
.bf_enable_beacon_filter
= 0;
1028 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_energy_delta = %d\n",
1029 le32_to_cpu(cmd
.bf_energy_delta
));
1030 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_energy_delta = %d\n",
1031 le32_to_cpu(cmd
.bf_roaming_energy_delta
));
1032 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_roaming_state = %d\n",
1033 le32_to_cpu(cmd
.bf_roaming_state
));
1034 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_threshold = %d\n",
1035 le32_to_cpu(cmd
.bf_temp_threshold
));
1036 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_fast_filter = %d\n",
1037 le32_to_cpu(cmd
.bf_temp_fast_filter
));
1038 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_temp_slow_filter = %d\n",
1039 le32_to_cpu(cmd
.bf_temp_slow_filter
));
1040 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_enable_beacon_filter = %d\n",
1041 le32_to_cpu(cmd
.bf_enable_beacon_filter
));
1042 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_debug_flag = %d\n",
1043 le32_to_cpu(cmd
.bf_debug_flag
));
1044 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "bf_escape_timer = %d\n",
1045 le32_to_cpu(cmd
.bf_escape_timer
));
1046 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_escape_timer = %d\n",
1047 le32_to_cpu(cmd
.ba_escape_timer
));
1048 pos
+= scnprintf(buf
+pos
, bufsz
-pos
, "ba_enable_beacon_abort = %d\n",
1049 le32_to_cpu(cmd
.ba_enable_beacon_abort
));
1051 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1054 #ifdef CONFIG_PM_SLEEP
1055 static ssize_t
iwl_dbgfs_d3_sram_write(struct file
*file
,
1056 const char __user
*user_buf
,
1057 size_t count
, loff_t
*ppos
)
1059 struct iwl_mvm
*mvm
= file
->private_data
;
1063 count
= min_t(size_t, count
, sizeof(buf
) - 1);
1064 if (copy_from_user(buf
, user_buf
, count
))
1067 if (sscanf(buf
, "%d", &store
) != 1)
1070 mvm
->store_d3_resume_sram
= store
;
1075 static ssize_t
iwl_dbgfs_d3_sram_read(struct file
*file
, char __user
*user_buf
,
1076 size_t count
, loff_t
*ppos
)
1078 struct iwl_mvm
*mvm
= file
->private_data
;
1079 const struct fw_img
*img
;
1080 int ofs
, len
, pos
= 0;
1083 u8
*ptr
= mvm
->d3_resume_sram
;
1085 img
= &mvm
->fw
->img
[IWL_UCODE_WOWLAN
];
1086 len
= img
->sec
[IWL_UCODE_SECTION_DATA
].len
;
1088 bufsz
= len
* 4 + 256;
1089 buf
= kzalloc(bufsz
, GFP_KERNEL
);
1093 pos
+= scnprintf(buf
, bufsz
, "D3 SRAM capture: %sabled\n",
1094 mvm
->store_d3_resume_sram
? "en" : "dis");
1097 for (ofs
= 0; ofs
< len
; ofs
+= 16) {
1098 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1100 hex_dump_to_buffer(ptr
+ ofs
, 16, 16, 1, buf
+ pos
,
1101 bufsz
- pos
, false);
1102 pos
+= strlen(buf
+ pos
);
1103 if (bufsz
- pos
> 0)
1107 pos
+= scnprintf(buf
+ pos
, bufsz
- pos
,
1108 "(no data captured)\n");
1111 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, pos
);
1119 #define MVM_DEBUGFS_READ_FILE_OPS(name) \
1120 static const struct file_operations iwl_dbgfs_##name##_ops = { \
1121 .read = iwl_dbgfs_##name##_read, \
1122 .open = simple_open, \
1123 .llseek = generic_file_llseek, \
1126 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name) \
1127 static const struct file_operations iwl_dbgfs_##name##_ops = { \
1128 .write = iwl_dbgfs_##name##_write, \
1129 .read = iwl_dbgfs_##name##_read, \
1130 .open = simple_open, \
1131 .llseek = generic_file_llseek, \
1134 #define MVM_DEBUGFS_WRITE_FILE_OPS(name) \
1135 static const struct file_operations iwl_dbgfs_##name##_ops = { \
1136 .write = iwl_dbgfs_##name##_write, \
1137 .open = simple_open, \
1138 .llseek = generic_file_llseek, \
1141 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \
1142 if (!debugfs_create_file(#name, mode, parent, mvm, \
1143 &iwl_dbgfs_##name##_ops)) \
1147 #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \
1148 if (!debugfs_create_file(#name, mode, parent, vif, \
1149 &iwl_dbgfs_##name##_ops)) \
1153 /* Device wide debugfs entries */
1154 MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush
);
1155 MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain
);
1156 MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram
);
1157 MVM_DEBUGFS_READ_FILE_OPS(stations
);
1158 MVM_DEBUGFS_READ_FILE_OPS(bt_notif
);
1159 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd
);
1160 MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off
);
1161 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats
);
1162 MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart
);
1163 MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain
);
1165 #ifdef CONFIG_PM_SLEEP
1166 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram
);
1169 /* Interface specific debugfs entries */
1170 MVM_DEBUGFS_READ_FILE_OPS(mac_params
);
1171 MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params
);
1172 MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params
);
1174 int iwl_mvm_dbgfs_register(struct iwl_mvm
*mvm
, struct dentry
*dbgfs_dir
)
1178 mvm
->debugfs_dir
= dbgfs_dir
;
1180 MVM_DEBUGFS_ADD_FILE(tx_flush
, mvm
->debugfs_dir
, S_IWUSR
);
1181 MVM_DEBUGFS_ADD_FILE(sta_drain
, mvm
->debugfs_dir
, S_IWUSR
);
1182 MVM_DEBUGFS_ADD_FILE(sram
, mvm
->debugfs_dir
, S_IWUSR
| S_IRUSR
);
1183 MVM_DEBUGFS_ADD_FILE(stations
, dbgfs_dir
, S_IRUSR
);
1184 MVM_DEBUGFS_ADD_FILE(bt_notif
, dbgfs_dir
, S_IRUSR
);
1185 MVM_DEBUGFS_ADD_FILE(bt_cmd
, dbgfs_dir
, S_IRUSR
);
1186 if (mvm
->fw
->ucode_capa
.flags
& IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD
)
1187 MVM_DEBUGFS_ADD_FILE(disable_power_off
, mvm
->debugfs_dir
,
1189 MVM_DEBUGFS_ADD_FILE(fw_rx_stats
, mvm
->debugfs_dir
, S_IRUSR
);
1190 MVM_DEBUGFS_ADD_FILE(fw_restart
, mvm
->debugfs_dir
, S_IWUSR
);
1191 MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain
, mvm
->debugfs_dir
,
1193 #ifdef CONFIG_PM_SLEEP
1194 MVM_DEBUGFS_ADD_FILE(d3_sram
, mvm
->debugfs_dir
, S_IRUSR
| S_IWUSR
);
1195 MVM_DEBUGFS_ADD_FILE(d3_test
, mvm
->debugfs_dir
, S_IRUSR
);
1196 if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR
| S_IWUSR
,
1197 mvm
->debugfs_dir
, &mvm
->d3_wake_sysassert
))
1202 * Create a symlink with mac80211. It will be removed when mac80211
1203 * exists (before the opmode exists which removes the target.)
1205 snprintf(buf
, 100, "../../%s/%s",
1206 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
1207 dbgfs_dir
->d_parent
->d_name
.name
);
1208 if (!debugfs_create_symlink("iwlwifi", mvm
->hw
->wiphy
->debugfsdir
, buf
))
1213 IWL_ERR(mvm
, "Can't create the mvm debugfs directory\n");
1217 void iwl_mvm_vif_dbgfs_register(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1219 struct dentry
*dbgfs_dir
= vif
->debugfs_dir
;
1220 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1224 * Check if debugfs directory already exist before creating it.
1225 * This may happen when, for example, resetting hw or suspend-resume
1227 if (!dbgfs_dir
|| mvmvif
->dbgfs_dir
)
1230 mvmvif
->dbgfs_dir
= debugfs_create_dir("iwlmvm", dbgfs_dir
);
1231 mvmvif
->dbgfs_data
= mvm
;
1233 if (!mvmvif
->dbgfs_dir
) {
1234 IWL_ERR(mvm
, "Failed to create debugfs directory under %s\n",
1235 dbgfs_dir
->d_name
.name
);
1239 if (iwlmvm_mod_params
.power_scheme
!= IWL_POWER_SCHEME_CAM
&&
1240 vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
)
1241 MVM_DEBUGFS_ADD_FILE_VIF(pm_params
, mvmvif
->dbgfs_dir
, S_IWUSR
|
1244 MVM_DEBUGFS_ADD_FILE_VIF(mac_params
, mvmvif
->dbgfs_dir
,
1247 if (vif
->type
== NL80211_IFTYPE_STATION
&& !vif
->p2p
&&
1248 mvmvif
== mvm
->bf_allowed_vif
)
1249 MVM_DEBUGFS_ADD_FILE_VIF(bf_params
, mvmvif
->dbgfs_dir
,
1253 * Create symlink for convenience pointing to interface specific
1254 * debugfs entries for the driver. For example, under
1255 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
1257 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
1259 snprintf(buf
, 100, "../../../%s/%s/%s/%s",
1260 dbgfs_dir
->d_parent
->d_parent
->d_name
.name
,
1261 dbgfs_dir
->d_parent
->d_name
.name
,
1262 dbgfs_dir
->d_name
.name
,
1263 mvmvif
->dbgfs_dir
->d_name
.name
);
1265 mvmvif
->dbgfs_slink
= debugfs_create_symlink(dbgfs_dir
->d_name
.name
,
1266 mvm
->debugfs_dir
, buf
);
1267 if (!mvmvif
->dbgfs_slink
)
1268 IWL_ERR(mvm
, "Can't create debugfs symbolic link under %s\n",
1269 dbgfs_dir
->d_name
.name
);
1272 IWL_ERR(mvm
, "Can't create debugfs entity\n");
1275 void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm
*mvm
, struct ieee80211_vif
*vif
)
1277 struct iwl_mvm_vif
*mvmvif
= iwl_mvm_vif_from_mac80211(vif
);
1279 debugfs_remove(mvmvif
->dbgfs_slink
);
1280 mvmvif
->dbgfs_slink
= NULL
;
1282 debugfs_remove_recursive(mvmvif
->dbgfs_dir
);
1283 mvmvif
->dbgfs_dir
= NULL
;